/* chrisplans.com
   ============================================================================
   Third time, and the first two were the same mistake in opposite directions.

   Pass one read "don't look vibe coded" as "be restrained" and produced a
   cream page with one navy accent. Pass two answered that with MORE colour: a
   hue per tab, gradient heroes, a tinted wash over every photograph.

   Both were wrong, because a colour SYSTEM is the generated-look tell. Real
   travel media has no accent palette that rotates by section. It has
   photographs, printed large, and chrome that gets out of the way.

   The rules now:

   1. Photographs are the design. Full strength, never tinted. The only thing
      laid over one is a neutral darkening at the bottom, where type sits.
   2. One accent, the sea, for links and the few things you can act on. Not for
      headings, not for section rules, not for decoration.
   3. Colour otherwise means something: the alert red where the guide says
      somebody could get hurt, and the beach flags, which are a real signalling
      system the group reads on the sand.
   4. ONE typeface, everywhere. Hierarchy comes from size, weight and tracking,
      not from a second face. A display serif dropped into a sans page reads as
      decoration borrowed from somewhere else.
   5. A real spacing scale, motion only on interactive things, no emoji as
      icons, no card inside a card.
   ========================================================================= */

:root {
  /* Surface. Pale sand, not the near-white it was. */
  --paper: #f0e9dc;        /* the page */
  --paper-lift: #f5efe4;   /* what the grain multiplies over */
  --paper-2: #e7dfcd;      /* a shade under the page: box fills */
  --paper-3: #fbf7ef;      /* a shade over the page: reserved */
  --card: #e7dfcd;         /* no white surfaces anywhere now */

  --ink: #16202a;
  --ink-2: #4f5a66;        /* body copy on sand */
  --ink-3: #6b6459;        /* labels, eyebrows, secondary: warmer */
  --rule: rgba(22, 32, 42, 0.18);
  --rule-soft: rgba(22, 32, 42, 0.12);

  /* One accent. Links, actions, live values. Never headings, never
     decoration. */
  --accent: #0e7490;
  /* NOT white: white on sand-adjacent UI reads wrong. */
  --on-accent: #f0e9dc;
  /* Written out rather than color-mixed, because it appears in every hover. */
  --accent-soft: rgba(14, 116, 144, 0.12);
  --accent-line: rgba(14, 116, 144, 0.35);

  --mango: #9a5c0f;        /* caution */
  --alert: #a8331f;        /* somebody could get hurt */

  /* Beach flags. The sanctioned exception. */
  --flag-safe: #3f6b4a;
  --flag-mixed: #9a7420;
  --flag-danger: #a8331f;

  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 22px;
  --s5: 30px; --s6: 52px; --s7: 84px;

  --display: 'Bricolage Grotesque', -apple-system, 'Segoe UI', Roboto, sans-serif;
  --text: -apple-system, BlinkMacSystemFont, 'Segoe UI Variable Text',
          'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;

  --ease: cubic-bezier(0.2, 0, 0.1, 1);
}

/* Self-hosted: a mockup can link Google Fonts, a private site should not hand
   a third party a request on every page load. Latin subset, variable 300-800.
   SIL Open Font License. */
@font-face {
  font-family: 'Bricolage Grotesque';
  src: url('/fonts/bricolage-grotesque.woff2') format('woff2');
  font-weight: 300 800;
  font-style: normal;
  font-display: swap;
}

* { box-sizing: border-box; }

/* Any figure being compared down a column: every time, every price, every
   phone number. */
.amt, .tel, .row .v, .countdown .n, .trip-out, td, .legtime {
  font-variant-numeric: tabular-nums;
}

/* Pinned, so a phone set to dark does not render the form controls dark
   underneath a light page. */
:root { color-scheme: light; }

/* Sand has tooth. A fractal-noise tile multiplied over --paper-lift lands back
   on --paper. Applied to the page, to panels that ride over photographs, and to
   secondary buttons. NOT to --paper-2 boxes and NOT to the inverted dark
   blocks: those are objects sitting on the sand and stay smooth. That contrast
   is the point. */
.grain, body {
  background-color: var(--paper-lift);
  background-image: url('/img/grain.svg');
  background-size: 160px 160px;
  background-blend-mode: multiply;
}

body {
  margin: 0;
  color: var(--ink);
  color: var(--ink);
  font-family: var(--text);
  font-size: 17px;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

h1, h2, h3 { margin: 0; font-weight: 400; }
p { margin: 0; }
ul { margin: 0; padding-left: 1.15em; }
li { margin: var(--s1) 0; }

a {
  color: var(--accent);
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  transition: opacity 120ms var(--ease);
}
a:hover { opacity: 0.7; }

.wrap { max-width: 720px; margin: 0 auto; padding: 0 var(--s4); }

/* --- display type ---------------------------------------------------------
   The one place the page raises its voice. Not a different face: the same one,
   set heavy and tight. At this size a sans left at weight 400 with default
   tracking reads as an accident rather than a decision. */

.display {
  font-family: var(--display);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.035em;
}

/* --- the door ------------------------------------------------------------ */

.boot {
  min-height: 100dvh; display: flex; align-items: center; justify-content: center;
  gap: var(--s2); color: var(--ink-2);
}
.spinner {
  width: 13px; height: 13px; border-radius: 50%;
  border: 1.5px solid var(--rule); border-top-color: var(--accent);
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* The first screen anyone sees, and previously the most generated-looking
   thing on the site: a teal-to-blue gradient with a form on it. Now it is the
   beach, at full strength, darkened only where the words are. */
.gate {
  min-height: 100dvh;
  display: flex; align-items: stretch; justify-content: center;
  padding: 30px 26px;
  color: #fff;
  /* Heavier and more even than a hero's. A hero carries a title; this carries
     a whole form, so the type runs the full height of the picture and a
     bottom-weighted wash left the placeholders sitting on bright water. */
  background:
    linear-gradient(to top,
      rgba(10, 18, 22, 0.95) 0%,
      rgba(10, 18, 22, 0.82) 45%,
      rgba(10, 18, 22, 0.40) 78%,
      rgba(10, 18, 22, 0.50) 100%),
    url('/img/playa-bonita.jpg') center 35% / cover no-repeat;
  background-attachment: scroll, fixed;
}
/* A fixed background costs more than it gives on a phone, and iOS ignores it. */
@media (max-width: 700px) {
  .gate { background-attachment: scroll, scroll; }
}

.gate-inner {
  width: 100%; max-width: 380px;
  display: flex; flex-direction: column;
}
.door-eyebrow {
  font-size: 11px; font-weight: 600; letter-spacing: 0.22em;
  text-transform: uppercase; color: rgba(255, 255, 255, 0.65);
}
/* The name sits at the bottom of whatever space is left above the form. */
.door-title { margin-block-start: auto; margin-bottom: 0; }
.door-bar { width: 52px; height: 2px; background: var(--accent); margin: 20px 0 22px; }
.door-row { display: flex; gap: 10px; }

/* Three columns over a hairline, each led by a numeral in a lighter teal so
   it reads on the photograph. */
.door-steps {
  margin-top: 22px; padding-top: 16px;
  display: flex; gap: 16px;
  border-top: 1px solid rgba(255, 255, 255, 0.22);
}
.door-steps > div { flex: 1; }
.door-steps .n {
  font-family: var(--display);
  font-size: 20px; font-weight: 700; line-height: 1; color: #7ec9cf;
}
.door-step-text {
  font-size: 12.5px; line-height: 1.4;
  color: rgba(255, 255, 255, 0.78); margin-top: 6px;
}

.gate h1 {
  font-family: var(--display);
  font-size: clamp(46px, 15vw, 62px);
  font-weight: 700;
  line-height: 0.92;
  letter-spacing: -0.04em;
}
/* The name used to sit above a strapline that supplied this gap. It does not
   any more, so the title carries its own. */
.door-title { margin-bottom: var(--s6); }
.gate .hint { color: color-mix(in srgb, #fff 68%, transparent); }
.gate label { color: color-mix(in srgb, #fff 72%, transparent); }
.gate .error { color: #ffd7cd; }

/* On colour, inputs are glass rather than white boxes. */
.gate input {
  padding: 14px;
  font-size: 16px;
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.4);
  border-radius: 2px;
  color: #fff;
}
.gate label {
  font-size: 11px; font-weight: 600; letter-spacing: 0.14em;
  color: rgba(255, 255, 255, 0.7); margin-bottom: 6px;
}
.gate input::placeholder { color: color-mix(in srgb, #fff 55%, transparent); }
.gate input:hover { border-color: color-mix(in srgb, #fff 60%, transparent); }
.gate input:focus-visible {
  border-color: #fff;
  background: rgba(255, 255, 255, 0.16);
  box-shadow: 0 0 0 3px rgba(14, 116, 144, 0.55);
}
/* A white shadow, because an ink one disappears into the photograph. */
.gate button {
  margin-top: 6px;
  padding: 16px 20px;
  font-size: 13.5px; letter-spacing: 0.14em;
  background: var(--accent); border-color: var(--accent); color: var(--on-accent);
  box-shadow: 4px 4px 0 rgba(255, 255, 255, 0.85);
}
.gate button:hover { transform: translate(-1px, -1px); box-shadow: 5px 5px 0 #fff; }
.gate button:active { transform: translate(4px, 4px); box-shadow: 0 0 0 #fff; }
.gate button.ghost { background: transparent; color: #fff; border-color: color-mix(in srgb, #fff 40%, transparent); }
.gate button.ghost:hover { background: color-mix(in srgb, #fff 10%, transparent); color: #fff; }

/* --- labels ---------------------------------------------------------------
   Used for section names and field labels only. Not decoration. */

/* Wide-tracked uppercase at 11px is a legibility floor, and this is the site's
   most repeated pattern. Bigger, tracked less, and darker. */
.eyebrow, label, .kicker {
  display: block;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-2);
}
label { margin-bottom: var(--s1); }
/* A label, not a highlight. */
.kicker { color: var(--ink-2); margin-bottom: var(--s2); }

/* --- forms ----------------------------------------------------------------- */

form { display: flex; flex-direction: column; gap: var(--s3); }

input, textarea, select {
  width: 100%;
  padding: 11px 13px;
  font: inherit;
  font-size: 16px;              /* 16px or iOS zooms on focus */
  color: var(--ink);
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 2px;
  transition: border-color 120ms var(--ease), box-shadow 120ms var(--ease);
}
input:hover, textarea:hover, select:hover { border-color: var(--ink-2); }
input:focus-visible, textarea:focus-visible, select:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
/* Dates and balances are numbers being compared down a column, so they line
   up and use the tabular figures. */
select, input[inputmode='numeric'] {
  font-variant-numeric: tabular-nums;
  padding: 8px 10px;
  text-align: right;
}
select { text-align: left; }

/* "Everything you can act on now announces itself." A solid fill, a hard
   offset shadow with no blur, and a press that physically moves the control
   down onto its own shadow. */
button {
  padding: 13px 18px;
  font: inherit;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--on-accent);
  background: var(--accent);
  border: 1px solid var(--accent);
  border-radius: 2px;
  cursor: pointer;
  box-shadow: 3px 3px 0 var(--ink);
  transition: transform 120ms var(--ease), box-shadow 120ms var(--ease);
}
button:hover { transform: translate(-1px, -1px); box-shadow: 4px 4px 0 var(--ink); }
button:active { transform: translate(3px, 3px); box-shadow: 0 0 0 var(--ink); }
button:disabled { opacity: 0.45; box-shadow: 2px 2px 0 var(--rule); cursor: default; }
button:disabled:hover { transform: none; box-shadow: 2px 2px 0 var(--rule); }
button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
button:disabled { opacity: 0.4; cursor: default; }
button:disabled:hover { filter: none; }

button.ghost {
  background: transparent;
  color: var(--ink);
  border-color: var(--ink);
  box-shadow: 2px 2px 0 var(--ink);
}
button.ghost:hover {
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  color: var(--accent);
  border-color: var(--accent);
  box-shadow: 3px 3px 0 var(--accent);
}
button.ghost:active { box-shadow: 0 0 0 var(--ink); }
button.danger { background: var(--alert); border-color: var(--alert); color: var(--on-accent); }

.error { color: var(--alert); font-size: 14px; }
.hint { color: var(--ink-2); font-size: 14.5px; line-height: 1.55; }

/* --- page furniture --------------------------------------------------------
   The hero is a colour field that changes with the tab you are on. Two stops
   of one hue mixed toward --deep: saturated enough to feel like somewhere,
   dark enough that white type stays legible on every one of them. */

/* A photograph, printed as large as the screen allows, with the type sitting
   in the darkened bottom of it. No colour over the image: tinting a photograph
   to match a palette is the thing that made these look synthetic. */
header.hero {
  position: relative;
  padding: var(--s7) 0 var(--s5);
  color: #fff;
  background: #0d1418;
}
header.hero > * { position: relative; z-index: 1; }

header.hero.has-art::before,
header.hero.has-art::after { content: ''; position: absolute; inset: 0; }
header.hero.has-art::before {
  background-image: var(--art);
  background-size: cover;
  background-position: var(--art-pos, center);
}
/* Neutral, and weighted to the bottom. Enough to read white type on, not
   enough to drain the picture. */
header.hero.has-art::after {
  background: linear-gradient(to top,
    rgba(8, 14, 18, 0.88) 0%,
    rgba(8, 14, 18, 0.55) 34%,
    rgba(8, 14, 18, 0.10) 68%,
    rgba(8, 14, 18, 0) 100%);
}

/* Nothing is written on the picture now, so it needs no scrim and no flexbox:
   it is just a photograph of a fixed height with a panel laid over its foot. */
header.hero.has-art {
  min-height: 300px;
  height: 44vh;
  max-height: 380px;
  padding: 0;
}
header.hero.has-art::after { display: none; }

/* The panel rides up over the image edge. This is 2A's signature move and the
   whole reason the screen reads as a spread. */
.titlecard {
  position: relative;
  z-index: 2;
  margin: -116px var(--s4) 0;
  padding: 24px 22px 22px;
  background-color: var(--paper-lift);
  background-image: url('/img/grain.svg');
  background-size: 160px 160px;
  background-blend-mode: multiply;
  border: 1px solid var(--rule-soft);
}
.titlecard .wrap { max-width: none; padding: 0; }
.titlecard .eyebrow {
  font-size: 11px; font-weight: 600; letter-spacing: 0.14em;
  color: var(--ink-2);
}
.titlecard h1 {
  font-family: var(--display);
  font-size: clamp(38px, 11.5vw, 50px);
  font-weight: 700;
  line-height: 0.9;
  letter-spacing: -0.045em;
  margin: 10px 0 0;
  color: var(--ink);
}
/* A rule with weight, not a hairline. */
.titlecard .countdown {
  margin-top: 20px;
  padding-top: 16px;
  border-top: 2px solid var(--ink);
  gap: 24px;
}
.titlecard .countdown .n {
  font-size: 38px;
  letter-spacing: -0.04em;
  color: var(--accent);
}
.titlecard .countdown .l {
  font-size: 10.5px; letter-spacing: 0.14em;
  color: var(--ink-2); margin-top: 5px;
}

/* The hub's title has no photograph behind it and does not need one. A black
   band there was just a band; on paper it reads as a masthead. */
header.hero.plain {
  padding: var(--s6) 0 var(--s4);
  background: none;
  color: var(--ink);
  border-bottom: 1px solid var(--rule);
}
header.hero.plain h1 { margin: 0; }
header.hero.plain .sub { color: var(--ink-2); }
header.hero .eyebrow { color: color-mix(in srgb, #fff 78%, transparent); }
header.hero h1 {
  font-family: var(--display);
  font-size: clamp(38px, 8.5vw, 56px);
  font-weight: 700;
  line-height: 1.02;
  letter-spacing: -0.045em;
  margin: var(--s2) 0 var(--s3);
}
header.hero .sub { color: color-mix(in srgb, #fff 84%, transparent); }
header.hero .lede { color: #fff; }
header.hero a { color: #fff; }

/* Photos on the trip tiles, same trick: picture under, cover colour over. */
.tile .tile-art {
  position: relative;
  background-size: cover;
  background-position: center;
}
.tile .tile-art > * { position: relative; z-index: 1; }
/* Same rule as the hero: the picture at full strength, darkened only under
   the title. The trip's cover colour is no longer washed over it. */
.tile .tile-art::before {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(to top,
    rgba(8, 14, 18, 0.86) 0%,
    rgba(8, 14, 18, 0.35) 55%,
    rgba(8, 14, 18, 0.05) 100%);
  z-index: 1;
}
header.hero.plain { padding: var(--s5) 0 var(--s5); }
header.hero.plain h1 { margin: 0; }
header.hero .eyebrow { color: color-mix(in srgb, #fff 74%, transparent); }
header.hero .lede { color: #fff; }
header.hero a { color: #fff; }

/* Numerals set like a printed table: aligned, quiet labels. */
.countdown { display: flex; gap: var(--s5); margin-top: var(--s5); }
.countdown .n {
  display: block;
  font-family: var(--display);
  font-size: 34px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.035em;
  font-variant-numeric: tabular-nums;
}
.countdown .l {
  font-size: 11px; letter-spacing: 0.09em; text-transform: uppercase;
  color: color-mix(in srgb, #fff 80%, transparent); margin-top: var(--s1);
}
/* Off a hero, on plain paper, it reads as ink. */
main .countdown .l { color: var(--ink-2); }
main .countdown .n { color: var(--accent); }

nav.tabs {
  position: sticky; top: 0; z-index: 20;
  border-bottom: 2px solid var(--ink);
  margin-top: 6px;
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--rule);
  overflow-x: auto; scrollbar-width: none;
}
nav.tabs::-webkit-scrollbar { display: none; }
nav.tabs .wrap { display: flex; gap: 6px; padding: 6px var(--s4) 0; }

/* Small caps, wide tracking, and the current tab is a solid block rather
   than an underline. Straight from the design's tab bar. */
nav.tabs button {
  background: none; border: 0; border-radius: 0;
  padding: 11px 15px;
  color: var(--ink-2);
  font-size: 12px; font-weight: 700;
  letter-spacing: 0.12em; text-transform: uppercase;
  white-space: nowrap;
  box-shadow: none;
  transition: background 120ms var(--ease), color 120ms var(--ease);
}
nav.tabs button:hover {
  transform: none; box-shadow: none;
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  color: var(--accent);
}
nav.tabs button[aria-current='true'] {
  color: var(--on-accent);
  background: var(--ink);
}
nav.tabs button[aria-current='true']:hover { background: var(--ink); color: var(--on-accent); }
nav.tabs .wrap { gap: 0; }

/* Sub-tabs, inside a page. A segmented control rather than a second row of
   underlines, so it never reads as competing with the main navigation. */
.subtabs {
  display: flex;
  gap: 2px;
  padding: 3px;
  margin: var(--s5) 0 var(--s4);
  background: var(--on-accent);
  border: 1px solid var(--rule);
  border-radius: 2px;
}
.subtabs button {
  flex: 1;
  padding: 9px 10px;
  font-size: 15px;
  font-weight: 500;
  color: var(--ink-2);
  background: none;
  border: 0;
  border-radius: 6px;
  transition: background 140ms var(--ease), color 140ms var(--ease);
}
.subtabs button:hover { background: none; color: var(--ink); filter: none; }
.subtabs button {
  font-size: 12px; font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase;
  box-shadow: none;
}
.subtabs button:hover { transform: none; box-shadow: none; }
.subtabs button[aria-current='true'] {
  color: var(--on-accent);
  background: var(--ink);
  box-shadow: none;
}

main { padding: var(--s6) 0 var(--s7); }
section { margin-bottom: var(--s6); }

/* A section head is a rule with a name on it, and the rule takes the tab's
   colour so the page is legible as one place at a glance. */
.sec-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--s3);
  padding-bottom: var(--s2);
  border-bottom: 2px solid var(--ink);
  margin-bottom: var(--s4);
}
.sec-head h2 {
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ink);
}
/* On the hub the section label leads in the accent, as 2A has it. */
body[data-view='hub'] .sec-head { border-bottom: 0; margin-bottom: var(--s3); }
body[data-view='hub'] .sec-head h2 {
  color: var(--accent);
  font-size: 11px; letter-spacing: 0.16em; font-weight: 600;
}
.sec-head .rule { display: none; }   /* the border does this job now */
/* A figure that belongs to the section, sat at the far end of its rule. */
.sec-head .total {
  margin-left: auto;
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* The opening statement of a section: bigger and lighter than body copy, so
   it reads as a lead paragraph rather than as another heading. */
.lede {
  font-family: var(--display);
  font-size: 22px;
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.025em;
  margin-bottom: var(--s4);
  max-width: 38ch;
}

/* --- blocks ---------------------------------------------------------------
   `.card` is reserved for things you can click. Prose blocks are set with
   space and a hairline, which is what stops the page reading as a grid of
   identical boxes. */

.card {
  background: transparent;
  border: 0;
  border-top: 1px solid var(--rule-soft);
  border-radius: 0;
  padding: var(--s4) 0;
  margin: 0;
}
.card:first-of-type { border-top: 0; padding-top: 0; }

.card h3 {
  font-family: var(--display);
  font-size: 22px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.03em;
  margin-bottom: var(--s1);
}
.meta { color: var(--ink-3); font-size: 15px; line-height: 1.6; }
.card > .meta + .meta { margin-top: var(--s2); }

/* --- a trip on the hub -----------------------------------------------------
   The same move as the trip screen: photograph, then a panel laid over its
   bottom edge. One idea used twice is what makes it a design rather than a
   collection of screens. */

.trip { margin-bottom: var(--s6); }
.trip-photo { height: 262px; background-size: cover; background-position: center; }
.trip-panel {
  margin: -56px var(--s4) 0;
  padding: 20px;
  position: relative;
  background-color: var(--paper-lift);
  background-image: url('/img/grain.svg');
  background-size: 160px 160px;
  background-blend-mode: multiply;
  border: 1px solid rgba(22, 32, 42, 0.16);
  box-shadow: 5px 5px 0 rgba(22, 32, 42, 0.1);
  transition: transform 140ms var(--ease), box-shadow 140ms var(--ease);
}
.trip-panel:hover {
  transform: translate(-2px, -2px);
  box-shadow: 7px 7px 0 color-mix(in srgb, var(--accent) 35%, transparent);
}
.trip-panel .eyebrow { font-size: 11px; letter-spacing: 0.14em; }
.trip-panel h2 {
  font-family: var(--display);
  font-size: 38px; font-weight: 700; line-height: 0.94; letter-spacing: -0.04em;
  margin: 8px 0 0;
}
.trip-rule {
  display: flex; align-items: baseline; gap: 10px;
  margin-top: 12px; padding-top: 12px;
  border-top: 1px solid var(--rule);
}
.trip-dates { font-size: 14.5px; color: var(--ink-3); }
.trip-out {
  margin-left: auto;
  font-size: 12px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  padding: 4px 8px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.trip-foot { display: flex; align-items: center; gap: 12px; margin-top: 16px; }

/* --- the hub bar ---------------------------------------------------------- */
.hubbar { border-bottom: 2px solid var(--ink); }
.hubbar .wrap {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px var(--s4);
}
.hubname {
  font-family: var(--display);
  font-size: 22px; font-weight: 700; letter-spacing: -0.03em; line-height: 1;
}
.whoami {
  display: flex; align-items: center; gap: 8px;
  background: none; border: 0; padding: 6px; border-radius: 2px;
  box-shadow: none;
  font-size: 11px; font-weight: 600; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--ink-2);
}
.whoami:hover {
  transform: none; box-shadow: none;
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}
.avatar {
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--accent); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 700; letter-spacing: 0;
}

/* Genuinely clickable: a trip, a person. These get a surface, and a colour
   edge that picks up the trip's own cover. */
.tile {
  display: block;
  position: relative;
  background: var(--card);

  border: 1px solid var(--rule);
  border-radius: 2px;
  overflow: hidden;
  margin-bottom: var(--s3);
  transition: border-color 140ms var(--ease), transform 140ms var(--ease),
              box-shadow 140ms var(--ease);
}
.tile::before {
  content: '';
  position: absolute; inset: 0 auto 0 0; width: 4px;
  background: var(--tile-accent, var(--accent));
}
.tile { box-shadow: 4px 4px 0 var(--ink); transition: transform 140ms var(--ease), box-shadow 140ms var(--ease); }
.tile:hover { transform: translate(-1px, -1px); box-shadow: 5px 5px 0 var(--accent); }

.row {
  display: flex; justify-content: space-between; gap: var(--s4);
  padding: var(--s3) 0;
  border-bottom: 1px solid var(--rule-soft);
}
.row:last-child { border-bottom: 0; }
.row .k { color: var(--ink-2); flex: 0 0 auto; }
.row .v { font-weight: 500; }
.row .v { text-align: right; }
.row .amt { font-variant-numeric: tabular-nums; white-space: nowrap; }

.chip {
  display: inline-block;
  padding: 3px 9px;
  margin-left: var(--s2);
  border: 1px solid var(--rule);
  border-radius: 99px;
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--ink-2);
  vertical-align: middle;
}
/* The recommendations. Filled, because they are the thing worth spotting. */
.chip.star {
  color: var(--on-accent);
  background: var(--accent);
  border-color: var(--accent);
}

/* Notes.
   The plain one is an indented aside, the way a printed guide sets a remark.
   Only `bad` carries the danger colour, because only `bad` means somebody
   could be hurt. */
.note {
  margin: var(--s3) 0;
  padding: var(--s2) 0 var(--s2) var(--s4);
  border-left: 3px solid var(--rule);
  font-size: 15.5px;
}
.note strong {
  display: block;
  font-weight: 600;
  margin-bottom: var(--s1);
}
.note.warn { border-left-color: var(--mango); }
.note.warn strong { color: var(--mango); }
/* The one that keeps a background, because it is the one that means somebody
   could get hurt and it should stop the eye. */
.note.bad {
  border-left-color: var(--alert);
  background: color-mix(in srgb, var(--alert) 8%, transparent);
  padding: var(--s3) var(--s4);
  border-radius: 0 4px 4px 0;
}
.note.bad strong { color: var(--alert); }

/* --- the five things ------------------------------------------------------- */

.five { counter-reset: five; }
.five .item {
  display: flex; gap: var(--s4);
  padding: var(--s4) 0;
  border-top: 1px solid var(--rule-soft);
}
.five .item:first-child { border-top: 0; padding-top: 0; }
.five .item::before {
  counter-increment: five;
  content: counter(five);
  min-width: 1.1em;
  font-size: 17px; font-weight: 700; color: var(--ink-2);
  flex: none; line-height: 1.5;
  font-variant-numeric: tabular-nums;
}
.five h3 {
  font-family: var(--display);
  font-size: 20px; font-weight: 600; letter-spacing: -0.02em;
  margin-bottom: var(--s1);
}

/* --- days ------------------------------------------------------------------ */

.dayhead { display: flex; align-items: baseline; gap: var(--s3); margin-bottom: var(--s1); }
.dow {
  font-family: var(--display);
  font-size: 24px; font-weight: 700; line-height: 1.1; letter-spacing: -0.035em;
}
.dnum { font-size: 12px; letter-spacing: 0.05em; text-transform: uppercase; font-weight: 600; color: var(--ink-2); }

.day .items { margin-top: var(--s3); }
.day .it { display: flex; gap: var(--s4); padding: var(--s3) 0; border-top: 1px solid var(--rule-soft); }
.day .when {
  flex: 0 0 44px;
  font-size: 11.5px; font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase;
  color: var(--ink-2); padding-top: 4px;
}

/* One night is set apart, the way a printed guide runs a full-bleed page. */
/* One night set apart. A gradient was never what made it feel special: being
   inverted is, the way a printed guide runs one page on a dark ground. */
.day.feature {
  color: var(--paper);
  background: var(--ink);
  padding: var(--s5) var(--s4);
  border-radius: 4px;
  border-top: 0;
  position: relative;
}
.day.feature .dnum { color: color-mix(in srgb, var(--paper) 72%, transparent); }
.day.feature .meta { color: color-mix(in srgb, var(--paper) 74%, transparent); }
.day.feature .when { color: color-mix(in srgb, var(--paper) 62%, transparent); }
.day.feature .it { border-top-color: color-mix(in srgb, var(--paper) 22%, transparent); }
.day.feature .note { border-left-color: color-mix(in srgb, var(--paper) 40%, transparent); }
.day.feature .note strong { color: var(--paper); }
.day.feature .chip { color: var(--paper); border-color: color-mix(in srgb, var(--paper) 45%, transparent); }
.day.feature .chip.star { background: color-mix(in srgb, var(--paper) 20%, transparent); border-color: transparent; color: var(--paper); }

.stamp {
  position: absolute; top: var(--s4); right: var(--s4);
  font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  color: color-mix(in srgb, var(--paper) 76%, transparent);
}

/* --- closures -------------------------------------------------------------- */

.nights { display: flex; gap: var(--s2); flex-wrap: wrap; margin-bottom: var(--s4); }
.night {
  flex: 1 1 128px;
  padding: var(--s3) 0 var(--s3) var(--s3);
  border-left: 3px solid var(--flag-safe);
  font-size: 14px; color: var(--ink-2);
}
.night b { display: block; color: var(--ink); font-weight: 600; margin-bottom: 2px; }
.night.warn { border-left-color: var(--flag-mixed); }
.night.warn b { color: var(--mango); }
.night.bad { border-left-color: var(--alert); }
.night.bad b { color: var(--alert); }

/* --- beaches ---------------------------------------------------------------
   The flag is a real signalling system, so it keeps its own colours rather
   than the tab's. */

.beach { display: flex; gap: var(--s3); align-items: flex-start; }
.flag { flex: none; width: 5px; align-self: stretch; min-height: 34px; border-radius: 3px; }
.flag.safe { background: var(--flag-safe); }
.flag.mixed { background: var(--flag-mixed); }
.flag.danger { background: var(--alert); }
.beach .b-top { display: flex; align-items: baseline; gap: var(--s2); flex-wrap: wrap; }
.beach .verdict { font-size: 14.5px; color: var(--ink-2); }

.legend { display: flex; gap: var(--s4); flex-wrap: wrap; font-size: 14px; color: var(--ink-2); margin-bottom: var(--s4); }
.legend span { display: flex; align-items: center; gap: var(--s2); }
.legend i { width: 4px; height: 16px; border-radius: 2px; display: inline-block; }

/* --- misc ------------------------------------------------------------------ */

/* --- the villa gallery -----------------------------------------------------
   A scroll strip on a phone, a grid once there is room. Photographs of the
   place you are sleeping in deserve to be looked at, not thumbnailed. */

.gallery {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 82%;
  gap: var(--s3);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  margin-bottom: var(--s5);
  padding-bottom: var(--s2);
}
.gallery::-webkit-scrollbar { display: none; }
.gallery figure { margin: 0; scroll-snap-align: start; }
.gallery img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 10px;
  background: var(--paper-2);
}
.gallery figcaption { margin-top: var(--s2); font-size: 13.5px; }

@media (min-width: 640px) {
  .gallery {
    grid-auto-flow: row;
    grid-template-columns: 1fr 1fr;
    grid-auto-columns: auto;
    overflow: visible;
  }
}

/* --- the summary cards ----------------------------------------------------
   One per screen on "The trip". A picture where the screen has one, the single
   fact that screen is about, and the whole thing is the tap target. */

.summary {
  display: flex;
  align-items: center;
  gap: var(--s4);
  padding: var(--s3) 0;
  border-top: 1px solid var(--rule-soft);
  cursor: pointer;
  transition: opacity 120ms var(--ease);
}
.summary:first-of-type { border-top: 0; }
.summary:hover {
  background: color-mix(in srgb, var(--accent) 6%, transparent);
  box-shadow: -12px 0 0 color-mix(in srgb, var(--accent) 6%, transparent),
              12px 0 0 color-mix(in srgb, var(--accent) 6%, transparent);
}
.summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: 4px; }
.summary img {
  flex: 0 0 84px;
  width: 84px; height: 84px;
  object-fit: cover;
  border-radius: 2px;
  background: var(--paper-2);
}
.summary-text { min-width: 0; flex: 1; }

/* The design's words: "navigable rows carry a chevron and tint on hover". */
.summary::after {
  content: '\203a';
  flex: none;
  font-size: 22px;
  line-height: 1;
  color: var(--ink-2);
  transition: transform 120ms var(--ease), color 120ms var(--ease);
}
.summary:hover::after { transform: translateX(3px); color: var(--accent); }
.summary-text h3 {
  font-family: var(--display);
  font-size: 20px; font-weight: 600;
  letter-spacing: -0.02em;
  margin: 2px 0;
}
.summary-text .meta { font-size: 14.5px; }

/* --- the left rail --------------------------------------------------------
   Ten tabs do not fit across a phone, so on a phone they stay a sticky bar you
   swipe. Given the width, they become a column instead: all ten visible, no
   swiping, and nothing to scroll back to. `:has` keeps this off the door,
   which has no nav at all. */

@media (min-width: 1000px) {
  #root:has(> nav.tabs) {
    display: grid;
    grid-template-columns: 220px minmax(0, 1fr);
    align-items: start;
  }
  #root:has(> nav.tabs) > nav.tabs {
    grid-column: 1;
    grid-row: 1 / span 4;
    position: sticky;
    top: 0;
    height: 100dvh;
    overflow-y: auto;
    overflow-x: visible;
    border-bottom: 0;
    border-right: 1px solid var(--rule);
    background: var(--paper);
    backdrop-filter: none;
  }
  #root:has(> nav.tabs) > nav.tabs .wrap {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    max-width: none;
    padding: var(--s5) var(--s4);
  }
  #root:has(> nav.tabs) > nav.tabs button {
    text-align: left;
    padding: 9px 12px;
    border-bottom: 0;
    border-radius: 6px;
  }
  #root:has(> nav.tabs) > nav.tabs button[aria-current='true'] {
    background: var(--accent-soft);
    color: var(--accent);
  }
  #root:has(> nav.tabs) > nav.tabs button[style*='margin-left'] { margin-left: 0 !important; margin-top: auto; }
  #root:has(> nav.tabs) > header.hero,
  #root:has(> nav.tabs) > main,
  #root:has(> nav.tabs) > footer { grid-column: 2; }
}

/* --- the box --------------------------------------------------------------
   The one heavy element: 2px ink border, a fill a shade under the page, and a
   5px hard shadow in the accent. Reserved for four things (your van, the chef
   budget, the staff tips, the host deadline) because its weight only works
   while it stays rare. No grain: it is an object on the sand, not the sand. */
.box {
  border: 2px solid var(--ink);
  background: var(--paper-2);
  padding: 20px;
  box-shadow: 5px 5px 0 var(--accent);
  margin-bottom: var(--s4);
}
.box.urgent { box-shadow: 5px 5px 0 var(--alert); }
.box .sec-head { border-bottom-color: var(--ink); }

/* A control sitting on a photograph, where an ink shadow would disappear. */
button.onart {
  color: #fff;
  background: rgba(255, 255, 255, 0.14);
  border: 1px solid rgba(255, 255, 255, 0.45);
  box-shadow: none;
}
button.onart:hover {
  background: rgba(255, 255, 255, 0.3);
  transform: none; box-shadow: none;
}
button.small { padding: 9px 14px; box-shadow: 2px 2px 0 var(--ink); }
button.small:hover { box-shadow: 3px 3px 0 var(--ink); }

/* Secondary buttons carry the grain, as the spec has it. */
button.ghost {
  background-color: var(--paper-lift);
  background-image: url('/img/grain.svg');
  background-size: 160px 160px;
  background-blend-mode: multiply;
}
button.ghost:hover { background-image: none; background-color: var(--accent-soft); }

/* --- links out ------------------------------------------------------------
   A "Map" tag beside a place name. Small and quiet: it is a way out of the
   page, not the point of the line it sits on. */

.maplink {
  margin-left: var(--s2);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-decoration: none;
  vertical-align: middle;
  border: 1px solid var(--accent-line);
  border-radius: 20px;
  padding: 2px 8px;
  white-space: nowrap;
}
.maplink:hover { background: var(--accent-soft); opacity: 1; }

/* A photograph of somewhere you could go, sitting above the thing it shows. */
.shot { margin: 0 0 var(--s4); }
.shot img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: 8px;
  background: var(--paper-2);
}
.shot figcaption { margin-top: var(--s2); font-size: 12.5px; opacity: 0.85; }

/* --- an award option -------------------------------------------------------
   Three lines on a phone: who and how much, then each leg with its flights and
   times. The times are the reason the row exists, so they are set in the
   tabular figures and are not allowed to wrap away from their airport. */

.award { padding: var(--s4) 0; border-top: 1px solid var(--rule-soft); }
.award:first-of-type { border-top: 0; padding-top: 0; }

.award-top {
  display: flex; justify-content: space-between; gap: var(--s3);
  align-items: baseline; margin-bottom: var(--s3);
}
.award-top strong { font-weight: 600; }
.award-top .amt { text-align: right; white-space: nowrap; }

.legline {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--s2);
  padding: var(--s2) 0;
  border-top: 1px solid var(--rule-soft);
}
.legwhen {
  flex: 0 0 38px;
  font-size: 11.5px; font-weight: 700; letter-spacing: 0.03em;
  text-transform: uppercase; color: var(--ink-2);
}
.legtime { font-variant-numeric: tabular-nums; font-weight: 500; }
.legline .meta { flex-basis: 100%; padding-left: 38px; font-size: 14px; }

.award-foot { margin-top: var(--s3); }
button.small { padding: 6px 12px; font-size: 13.5px; }

.pill-list { display: flex; flex-wrap: wrap; gap: var(--s2); }
.pill {
  font-size: 14px; padding: 5px 12px;
  border: 1px solid var(--rule);
  background: transparent;
  border-radius: 20px;
  color: var(--ink);
}
.dim { opacity: 0.55; }
.empty { color: var(--ink-2); font-size: 15px; }
.tel { font-variant-numeric: tabular-nums; white-space: nowrap; }

footer {
  border-top: 1px solid var(--rule);
  padding: var(--s5) 0 var(--s7);
  color: var(--ink-2); font-size: 14.5px;
}
footer p + p { margin-top: var(--s1); }
/* Required by the photo licences, so it is quiet but it is never hidden. */
.credits { margin-top: var(--s3); font-size: 13px; opacity: 0.9; }

.admin-row { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }
.admin-row .who { flex: 1 1 190px; min-width: 0; }
.admin-row .who strong { display: block; font-weight: 600; }
.admin-row button { padding: 7px 13px; font-size: 14px; }

.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s4); }
@media (max-width: 560px) { .grid2 { grid-template-columns: 1fr; } }

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

/* The van time, the one number that box exists for. */
.vanwhen { font-family: var(--display); font-size: 38px; font-weight: 700; letter-spacing: -0.045em; line-height: 1; margin-top: 12px; font-variant-numeric: tabular-nums; }
