/* ==========================================================================
   TIME BOULEVARD - shared stylesheet, duna/Kestrel-derived system.

   This is an explicit, scoped departure from the locked Time Boulevard
   brand guideline: Kestrel's own type (Figtree + IBM Plex Mono), radius,
   shadow and colour system are kept as-is, per Dewi's direct instruction
   to retain the duna.com-derived visual language and park the six-hex
   TB palette for this build. Not a redefinition of the guideline -
   a scoped experiment on top of it.

   Sections, in order:
     1. Theme      tokens: paper, ink, the six pigments lifted from the art
     2. Base       reset, type, buttons, shared furniture
     3. Nav        transparent over the art, white glass once you scroll
     4. Hero       the painting, the scrim, the line
     7. Rows       list primitive - Notebook entries, Shelf items
     8. Contact    closing band and footer
     9. Responsive one stack of breakpoints
    10. Motion     prefers-reduced-motion, last so it wins
   ========================================================================== */

/* -- 1. THEME ------------------------------------------------------------- */
:root {
  --paper:   #FFFFFF;
  --ground:  #FDFBF7;
  --sand:    #F7F3EC;
  --ink:     #1A1917;
  --ink-2:   #565149;
  --ink-3:   #8C877D;
  --line:    #E9E4DA;
  --line-2:  #D8D2C5;

  --peach:   #F0A277;
  --blush:   #F2B3BC;
  --apricot: #FBC993;
  --sage:    #9DB87C;
  --teal:    #7FA9A1;
  --plum:    #A96C90;

  /* The dropdown is the one dark surface in a light system, duna's move. It is
     the house ink at 88%, not pure black: translucent over warm paper it reads
     as a deep warm charcoal, and the page tint stays faintly alive underneath. */
  --panel-ink:      rgba(26, 25, 23, 0.88);
  --panel-text:     #FFFFFF;
  --panel-text-2:   rgba(255, 255, 255, 0.60);
  --panel-line:     rgba(255, 255, 255, 0.14);
  --panel-hover:    rgba(255, 255, 255, 0.08);

  --sky-1: #F4B78A;
  --sky-2: #F9CFAE;
  --sky-3: #FDE7D8;

  --sans: 'Figtree', 'Helvetica Neue', Arial, sans-serif;
  --mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  --t-display: clamp(2.9rem, 6.4vw, 5.375rem);
  --t-h2:      clamp(2rem, 3.6vw, 3.125rem);
  --t-title:   clamp(2.25rem, 4.4vw, 3.75rem);
  --t-h3:      1.25rem;
  --t-lead:    clamp(1.0625rem, 1.35vw, 1.3125rem);
  --t-body:    1rem;
  --t-small:   0.875rem;
  --t-micro:   0.75rem;

  --s4: 4px;    --s8: 8px;    --s12: 12px;  --s16: 16px;  --s20: 20px;
  --s24: 24px;  --s32: 32px;  --s40: 40px;  --s56: 56px;  --s72: 72px;
  --s96: 96px;  --s128: 128px;

  --shell: 1240px;
  --gutter: var(--s32);
  --nav-h: 76px;
  --radius: 16px;
  --radius-lg: 24px;

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  /* The soft one: a long tail that decelerates almost to a stop, which is what
     makes a panel look like it settled rather than snapped. */
  --ease-soft: cubic-bezier(0.16, 1, 0.3, 1);
  --fast: 180ms;
  --slow: 460ms;
  --reveal: 380ms;
}

/* -- 2. BASE -------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--t-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
h1, h2, h3 { font-weight: 600; letter-spacing: -0.032em; line-height: 1.02; margin: 0; text-wrap: balance; }
p { margin: 0; }
a { color: inherit; text-decoration: none; }
ul { margin: 0; padding: 0; list-style: none; }
img { max-width: 100%; display: block; }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; border-radius: 4px; }

.shell { width: 100%; max-width: var(--shell); margin-inline: auto; padding-inline: var(--gutter); }
section[id] { scroll-margin-top: calc(var(--nav-h) + var(--s16)); }

.eyebrow {
  font-family: var(--mono);
  font-size: var(--t-micro);
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.section-head { max-width: 660px; }
.section-head h2 { font-size: var(--t-h2); margin-top: var(--s16); }
.section-head p { color: var(--ink-2); font-size: var(--t-lead); line-height: 1.5; margin-top: var(--s20); }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s8);
  height: 52px; padding-inline: var(--s32); border-radius: 999px;
  font-family: var(--sans); font-size: 1.0625rem; font-weight: 500;
  border: 1px solid transparent; cursor: pointer; white-space: nowrap;
  transition: background var(--fast) var(--ease), color var(--fast) var(--ease),
              border-color var(--fast) var(--ease), transform var(--fast) var(--ease),
              box-shadow var(--fast) var(--ease);
}
.btn-solid { background: var(--ink); color: #FFF; }
.btn-solid:hover { transform: translateY(-2px); box-shadow: 0 12px 28px -14px rgba(26, 25, 23, 0.7); }
.btn-outline { background: transparent; color: var(--ink); border-color: var(--line-2); }
.btn-outline:hover { background: var(--sand); border-color: var(--ink-3); transform: translateY(-2px); }
.btn-sm { height: 42px; padding-inline: var(--s20); font-size: var(--t-small); font-weight: 500; }
.btn .arrow { transition: transform var(--fast) var(--ease); }
.btn:hover .arrow { transform: translateX(3px); }

/* Currently unused - the Sign in control was removed on 2026-08-14. Kept as
   the pattern for any not-yet-built control: inert on purpose, a span rather
   than a link, so there is nothing to click and nowhere to land. It says why
   on hover and on focus, so the answer is never mouse-only. */
.btn.is-soon { position: relative; color: var(--ink-2); border-color: var(--line); cursor: not-allowed; }
.btn.is-soon:hover { background: transparent; border-color: var(--line); transform: none; box-shadow: none; }

/* -- 3. NAV --------------------------------------------------------------- */
.nav {
  position: sticky; top: 0; z-index: 100; height: var(--nav-h);
  background: transparent; border-bottom: 1px solid transparent;
  backdrop-filter: blur(0px); -webkit-backdrop-filter: blur(0px);
  transition: background var(--slow) var(--ease), border-color var(--slow) var(--ease),
              backdrop-filter var(--slow) var(--ease);
}
.nav.is-scrolled {
  background: rgba(253, 251, 247, 0.72); border-bottom-color: var(--line);
  backdrop-filter: blur(20px) saturate(180%); -webkit-backdrop-filter: blur(20px) saturate(180%);
}
.nav-inner { height: 100%; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: var(--s24); max-width: 1440px; }
/* The mark is the Tb monogram cut out of the full lockup and keyed to a
   transparent ground, so it sits on the painting and on the glass alike.
   The wordmark is Figtree, not the serif inside the source file, and not
   mono - mono is never display type here. */
.brand { display: inline-flex; align-items: center; gap: var(--s12); font-size: 1.375rem; font-weight: 600; letter-spacing: 0.005em; justify-self: start; }
.brand-mark { display: block; width: auto; height: 28px; transition: transform var(--slow) var(--ease); }
.brand:hover .brand-mark { transform: translateY(-2px); }

.nav-menu { display: flex; align-items: center; justify-content: center; gap: var(--s8); }
.nav-item { position: relative; }
.nav-link {
  position: relative; display: inline-flex; align-items: center; gap: var(--s8);
  height: 38px; padding-inline: var(--s16); border-radius: 999px;
  font-size: 1.0625rem; font-weight: 500; color: var(--ink-2);
  transition: color var(--fast) var(--ease), background var(--fast) var(--ease);
}
.nav-link::after {
  content: ''; position: absolute; left: 50%; bottom: 4px; width: 4px; height: 4px;
  margin-left: -2px; border-radius: 50%; background: var(--peach); opacity: 0;
  transform: translateY(3px); transition: opacity var(--fast) var(--ease), transform var(--fast) var(--ease);
}
.nav-link:hover, .nav-item:focus-within > .nav-link { color: var(--ink); background: rgba(26, 25, 23, 0.05); }
.nav-link:hover::after, .nav-item:focus-within > .nav-link::after { opacity: 1; transform: translateY(0); }
.nav-link[aria-current="page"] { color: var(--ink); }
.nav-link[aria-current="page"]::after { opacity: 1; transform: translateY(0); }

.caret { width: 10px; height: 10px; opacity: 0.6; transition: transform var(--fast) var(--ease); }
.nav-item:hover .caret, .nav-item:focus-within .caret { transform: rotate(180deg); }

/* Panel proportions are duna's, not a shrunk version of them: the panel is
   wide enough that a sub-line mostly holds one line, the gutter between the
   two columns is wide enough to read as a gutter, and every row is the same
   height so one wrapping sub-line cannot break the rhythm of the rest.
   `translate(-50%, ...)` centres it on its trigger, which is why the old
   -240px margin is gone - the width is now free to change on its own. */
.nav-panel {
  position: absolute; top: calc(100% + 8px); left: 50%;
  width: min(760px, calc(100vw - var(--s40)));
  padding: var(--s16); border: 1px solid var(--panel-line); border-radius: var(--radius-lg);
  background: var(--panel-ink); backdrop-filter: blur(24px) saturate(180%);
  -webkit-backdrop-filter: blur(24px) saturate(180%); box-shadow: 0 30px 64px -28px rgba(26, 25, 23, 0.55);
  display: grid; grid-template-columns: 1fr 1fr; grid-auto-rows: 1fr;
  column-gap: var(--s32); row-gap: var(--s4);
  opacity: 0; visibility: hidden;
  /* Origin at the top edge, so the scale reads as the panel growing down out
     of its trigger instead of inflating from its own middle. */
  transform-origin: top center;
  transform: translate(-50%, -10px) scale(0.97);
  transition: opacity var(--reveal) var(--ease-soft), transform var(--reveal) var(--ease-soft),
              visibility var(--reveal) var(--ease-soft);
}
/* The rule down the gutter. Absolutely positioned, so it is not a grid item
   and never takes a cell of its own. */
.nav-panel::before {
  content: ''; position: absolute; top: var(--s20); bottom: var(--s20); left: 50%;
  width: 1px; background: var(--panel-line); pointer-events: none;
}
/* Under four links the two-column grid leaves an empty bottom-right cell with
   the gutter rule running full height past it. Narrow to one column and drop
   the rule: a divider with nothing on one side of it is not dividing anything. */
.nav-panel:not(:has(> .panel-link:nth-child(4))) {
  width: min(400px, calc(100vw - var(--s40)));
  grid-template-columns: 1fr;
}
.nav-panel:not(:has(> .panel-link:nth-child(4)))::before { display: none; }
.nav-item:hover .nav-panel, .nav-item:focus-within .nav-panel {
  opacity: 1; visibility: visible; transform: translate(-50%, 0) scale(1);
}
/* The links come up just behind the panel, each a beat after the one before.
   Delay only on the way in - on the way out they leave together, because a
   staggered exit reads as lag, not as craft. */
.panel-link {
  opacity: 0; transform: translateY(6px);
  transition: opacity var(--fast) var(--ease), transform var(--fast) var(--ease),
              background var(--fast) var(--ease);
}
.nav-item:hover .panel-link, .nav-item:focus-within .panel-link { opacity: 1; transform: translateY(0); }
.nav-item:hover .panel-link:nth-child(1), .nav-item:focus-within .panel-link:nth-child(1) { transition-delay: 60ms; }
.nav-item:hover .panel-link:nth-child(2), .nav-item:focus-within .panel-link:nth-child(2) { transition-delay: 95ms; }
.nav-item:hover .panel-link:nth-child(3), .nav-item:focus-within .panel-link:nth-child(3) { transition-delay: 130ms; }
.nav-item:hover .panel-link:nth-child(4), .nav-item:focus-within .panel-link:nth-child(4) { transition-delay: 165ms; }
.nav-item:hover .panel-link:nth-child(5), .nav-item:focus-within .panel-link:nth-child(5) { transition-delay: 200ms; }
.nav-item:hover .panel-link:nth-child(6), .nav-item:focus-within .panel-link:nth-child(6) { transition-delay: 235ms; }
.panel-link { display: block; padding: var(--s12) var(--s16); border-radius: 12px; color: var(--panel-text); }
.panel-link:hover { background: var(--panel-hover); }
.panel-link strong { display: block; font-size: var(--t-body); font-weight: 500; margin-bottom: 3px; }
/* One line, always. The panel is sized so nothing in it truncates today; the
   ellipsis is the failure mode for a sub-line written longer tomorrow, which
   is a better failure than a row growing taller than the row beside it. */
.panel-link span {
  display: block; font-size: var(--t-small); line-height: 1.5; color: var(--panel-text-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.nav-actions { display: flex; align-items: center; gap: var(--s12); justify-self: end; }
.nav-toggle {
  display: none; width: 42px; height: 42px; align-items: center; justify-content: center;
  background: transparent; border: 1px solid var(--line-2); border-radius: 999px; color: var(--ink); cursor: pointer;
}

/* -- 4. HERO -------------------------------------------------------------- */
.hero {
  position: relative; margin-top: calc(var(--nav-h) * -1); min-height: 92svh;
  display: grid; align-content: end; padding-bottom: clamp(var(--s40), 7vh, var(--s96)); isolation: isolate;
}
.hero-art { position: absolute; inset: 0; z-index: -2; width: 100%; height: 100%; object-fit: cover; display: block; }
.hero-scrim {
  position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: radial-gradient(58% 42% at 50% 88%, rgba(255,255,255,0.96) 0%, rgba(255,255,255,0.55) 45%, rgba(255,255,255,0) 72%),
              linear-gradient(180deg, rgba(255,255,255,0) 62%, rgba(253,251,247,0.9) 92%, var(--ground) 100%);
}
#sky .s1 { stop-color: var(--sky-1); }
#sky .s2 { stop-color: var(--sky-2); }
#sky .s3 { stop-color: var(--sky-3); }
#water .s1 { stop-color: var(--blush); }
.peak-teal { fill: var(--teal); }

.hero-content { text-align: center; }
.hero h1 { font-size: var(--t-display); font-weight: 600; letter-spacing: -0.038em; line-height: 0.98; margin-top: var(--s32); }
.hero-lead { max-width: 42ch; margin: var(--s24) auto 0; font-size: var(--t-lead); line-height: 1.45; color: var(--ink-2); font-style: italic; }
.hero-cta { margin-top: var(--s32); display: flex; justify-content: center; gap: var(--s12); flex-wrap: wrap; }
.scroll-cue { width: 34px; height: 4px; border-radius: 999px; background: var(--ink-3); opacity: 0.45; margin: var(--s40) auto 0; animation: cue-drift 2.8s var(--ease) infinite; }
@keyframes cue-drift { 0%, 100% { transform: translateY(0); opacity: 0.45; } 50% { transform: translateY(5px); opacity: 0.2; } }

/* -- 4b. PAGE HERO (interior pages, no painted art) ------------------------ */
.page-hero { padding-block: var(--s96) var(--s72); border-bottom: 1px solid var(--line); background: var(--ground); }
.page-hero h1 { font-size: var(--t-h2); margin-top: var(--s16); }
.page-hero p { color: var(--ink-2); font-size: var(--t-lead); line-height: 1.5; margin-top: var(--s20); max-width: 60ch; }

/* Generic interior band. Same vertical rhythm as .split and .features, with
   none of their grid. */
.band { padding-block: var(--s128); }
.band.is-sand { background: var(--sand); border-block: 1px solid var(--line); }
/* Two bands on the same ground would stack 256px of air between them. A change
   of ground earns the full gap; a continuation on the same ground does not.
   These two rules have EQUAL specificity, so the second must stay second -
   it is what restores the gap after a sand band. Do not reorder. */
.band + .band:not(.is-sand) { padding-top: 0; }
.band.is-sand + .band { padding-top: var(--s128); }
/* The page hero already closes with 72px and a rule. A full band gap on top of
   that stacks 200px of air before the first content on every interior page. */
.page-hero + .band { padding-top: var(--s56); }

/* .prose lives further down, after the containers it can be nested inside.
   See the note above it. */

/* The one form on the site. No price, no checkout - it takes an address and
   nothing else. */
.signup { display: flex; gap: var(--s12); margin-top: var(--s32); max-width: 480px; flex-wrap: wrap; }
.signup input {
  flex: 1 1 220px; height: 52px; padding-inline: var(--s20);
  border: 1px solid var(--line-2); border-radius: 999px; background: var(--paper);
  font-family: var(--sans); font-size: 1.0625rem; color: var(--ink);
  transition: border-color var(--fast) var(--ease);
}
.signup input::placeholder { color: var(--ink-3); }
.signup input:focus { border-color: var(--ink-3); }
.signup-note { margin-top: var(--s16); font-family: var(--mono); font-size: var(--t-micro); letter-spacing: 0.04em; color: var(--ink-3); }

.contact-links { display: flex; gap: var(--s24); justify-content: center; flex-wrap: wrap; margin-top: var(--s32); }
.contact-links a { font-family: var(--mono); font-size: var(--t-small); color: var(--ink-2); border-bottom: 1px solid var(--line-2); transition: color var(--fast) var(--ease), border-color var(--fast) var(--ease); }
.contact-links a:hover { color: var(--ink); border-color: var(--ink); }

/* -- 8b. PROSE ------------------------------------------------------------ */
/* Deliberately last of the block-level rules. `.split-copy p`, `.section-head p`
   and `.page-hero p` all style a bare <p> at the same specificity, so whichever
   is written later wins. .prose is meant to hold its own measure and rhythm
   wherever it is nested, so it goes after all of them rather than fighting them
   with a doubled class. Keep it here. */
.prose { max-width: 60ch; }
h1 + .prose, h2 + .prose { margin-top: var(--s24); }
.prose p { color: var(--ink-2); font-size: var(--t-body); line-height: 1.7; margin-top: 0; }
.prose p + p { margin-top: var(--s20); }
.prose b, .prose strong { color: var(--ink); font-weight: 600; }
.prose em { font-style: italic; }

/* Long-form furniture. The global h1,h2,h3 rule zeroes margins and sets a 1.02
   leading for display type, which is wrong inside running prose, so both are
   restored here. */
.prose h2 { font-size: 1.5rem; line-height: 1.25; margin-top: var(--s40); }
.prose h3 { font-size: var(--t-h3); line-height: 1.3; margin-top: var(--s32); }
.prose h2 + p, .prose h3 + p { margin-top: var(--s16); }
.prose ul { margin-top: var(--s20); display: grid; gap: var(--s8); }
.prose li { position: relative; padding-left: var(--s20); color: var(--ink-2); line-height: 1.7; }
.prose li::before { content: ''; position: absolute; left: 0; top: 0.7em; width: 6px; height: 1px; background: var(--ink-3); }
.prose blockquote { margin: var(--s32) 0 0; padding-left: var(--s24); border-left: 2px solid var(--peach); }
.prose blockquote p { color: var(--ink); font-size: var(--t-lead); line-height: 1.5; }
.prose hr { margin: var(--s40) 0 0; border: 0; border-top: 1px solid var(--line); }
.prose p > a { border-bottom: 1px solid var(--line-2); transition: border-color var(--fast) var(--ease); }
.prose p > a:hover { border-color: var(--ink); }
.prose .link-into { display: inline-block; margin-top: var(--s24); font-family: var(--mono); font-size: var(--t-small); border-bottom: 1px solid var(--ink); }

/* -- 7. ROWS (list primitive - Notebook entries, Shelf items) -------------- */
.rows { margin-top: var(--s24); border: 1px solid var(--line); border-radius: 14px; overflow: hidden; }
.row { display: grid; grid-template-columns: 140px 1fr 100px; gap: var(--s16); align-items: center; padding: var(--s16) var(--s20); border-bottom: 1px solid var(--line); font-size: var(--t-small); transition: background var(--fast) var(--ease); }
.row:last-child { border-bottom: 0; }
.row:hover { background: var(--sand); }
.row-head { font-family: var(--mono); font-size: var(--t-micro); letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3); background: var(--sand); }
.row-head:hover { background: var(--sand); }
.row-name { font-family: var(--sans); font-size: var(--t-body); font-weight: 500; color: var(--ink); }
.row-src { font-family: var(--mono); color: var(--ink-3); }
.row-score { font-family: var(--mono); color: var(--ink); text-align: right; }
/* Two-column rows, for lists with nothing true to put in the third slot. An
   empty column held open reads as missing data - same reasoning as .post.is-textonly. */
.rows.is-pair .row { grid-template-columns: 160px 1fr; }
/* The global `a` rule strips underlines, and every link style on this site adds
   its own back. An inline link inside row copy had none, so it read as plain
   text. Underline rather than border-bottom, so it survives wrapping. */
.row-name a { text-decoration: underline; text-decoration-color: var(--ink-3); text-underline-offset: 0.18em; }
.row-name a:hover { text-decoration-color: var(--ink); }
.rows + .post-stamp { display: block; margin-top: var(--s16); }

.chip { display: inline-flex; align-items: center; padding: 3px var(--s12); border-radius: 999px; font-family: var(--mono); font-size: var(--t-micro); letter-spacing: 0.05em; }
.chip.is-open { background: rgba(157, 184, 124, 0.2); color: #55703B; }
.chip.is-progress { background: rgba(240, 162, 119, 0.18); color: #A05B2E; }
.chip.is-soon { background: rgba(169, 108, 144, 0.14); color: var(--plum); }

/* -- 7c. POSTS (the reading list, duna /news-derived) ----------------------- */
/* One row per piece: photograph left, then a small tag-and-date line, the
   title, and the standfirst. A row is one <a>, separated by a hairline, with
   no outer box - structure is hairlines here. The fill on hover bleeds past
   the text column via the negative inline margin, so the text stays on the
   page grid while the highlight reads as a full row.
   A post with no photograph drops the image column rather than holding an
   empty box open, and `.is-compact` is the text-only variant that closes an
   article: three photographs under a piece competes with the piece. */
.posts { margin-top: var(--s40); border-top: 1px solid var(--line); }
.post {
  display: grid; grid-template-columns: 260px minmax(0, 1fr); gap: var(--s32);
  align-items: start; padding: var(--s24) var(--s20);
  margin-inline: calc(var(--s20) * -1);
  border-bottom: 1px solid var(--line); border-radius: var(--radius);
  transition: background var(--fast) var(--ease);
}
.post.is-textonly, .posts.is-compact .post { grid-template-columns: 1fr; }
.post:hover { background: var(--sand); }
.post-thumb {
  display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover;
  border: 1px solid var(--line); border-radius: var(--radius);
}
/* Structural: it groups the three text elements so they are one grid child,
   not three. min-width:0 is what lets a long unbroken word wrap instead of
   pushing the row wider than its column. */
.post-copy { min-width: 0; }
.post-stamp { font-family: var(--mono); font-size: var(--t-micro); letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3); }
.post-title { margin-top: var(--s12); font-size: clamp(1.25rem, 1.7vw, 1.5rem); font-weight: 600; letter-spacing: -0.032em; line-height: 1.2; }
.posts.is-compact .post-title { font-size: var(--t-h3); }
.post-standfirst { margin-top: var(--s12); color: var(--ink-2); font-size: var(--t-body); line-height: 1.55; max-width: 60ch; }
.posts-empty { margin-top: var(--s40); padding-top: var(--s24); border-top: 1px solid var(--line); font-family: var(--mono); font-size: var(--t-small); color: var(--ink-3); }

/* THE CARD WALL. Rewriting History is a numbered sequence of photographs with
   short titles, so it reads as a wall rather than a list: picture, title, one
   grey meta line, three across. The row layout above still serves the prose
   rooms, where a long standfirst needs the width. No dividing rules here - the
   gap between cards is the only separator, which is what stops a wall of
   photographs looking like a table. */
/* The band opens tighter than a prose room. A list needs its top rule pushed
   clear of the hero; a wall has no rule, so that same space reads as a hole
   between the standfirst and the first photograph. */
.band.is-wall { padding-top: var(--s72); }
.posts.is-grid {
  margin-top: 0; border-top: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s56) var(--s32);
}
.posts.is-grid .post {
  display: block; padding: 0; margin-inline: 0;
  border-bottom: 0; border-radius: 0;
}
.posts.is-grid .post:hover { background: none; }
.posts.is-grid .post-thumb {
  border-radius: var(--radius-lg);
  transition: transform var(--fast) var(--ease);
}
/* The lift is the whole hover. A background wash behind a card reads as a
   selected row, which is the list behaviour this layout is getting away from. */
.posts.is-grid .post:hover .post-thumb { transform: translateY(-3px); }
.posts.is-grid .post:hover .post-title { text-decoration: underline; text-underline-offset: 0.18em; }
.posts.is-grid .post-copy { margin-top: var(--s20); }
.posts.is-grid .post-title { margin-top: 0; font-size: clamp(1.125rem, 1.35vw, 1.3125rem); }
/* Baseline alignment, not centre: the rule has to sit on the same line as the
   type it separates, and the stamp is mono while the standfirst is not. */
.posts.is-grid .post-meta {
  margin-top: var(--s12); display: flex; align-items: baseline;
  flex-wrap: wrap; gap: 0 var(--s12);
}
.posts.is-grid .post-stamp { flex: none; }
.posts.is-grid .post-rule { flex: none; width: 18px; height: 1px; background: var(--line); transform: translateY(-0.28em); }
.posts.is-grid .post-standfirst {
  margin-top: 0; max-width: none;
  font-size: var(--t-small); line-height: 1.5; color: var(--ink-3);
}

/* -- 7d. ARTICLE (the post page, duna/news-derived) ------------------------- */
/* Order is the whole format: eyebrow, headline, lead, a byline sitting on a
   hairline, the photograph, one reading column, then the room's other pieces.
   No sidebar, no share rail, no author card. The photograph is the only thing
   on the page allowed to be full shell width; the words stay at 60ch.
   Replaces .post-meta, which was the old date-under-the-standfirst line. */
/* Centred, the way duna's article opens: room and date on one small line, the
   headline under it at --t-title, the lead under that. No byline - one author,
   and her name is the domain. The whole head is centred and the body is not;
   that switch is what makes the head read as a title page. */
.article-head { padding-block: var(--s12) 0; text-align: center; }
.article-head h1 { font-size: var(--t-title); margin-top: var(--s12); max-width: 20ch; margin-inline: auto; }

/* The language toggle. It is two links and a label, never a script: a
   translated piece has two real URLs, so switching is navigation, not state.
   The active side is the filled pill; the other is the link. Do not rebuild
   this as a button that hides a div - that costs the English version its own
   URL, its place in search, and its correct document language. */
.lang-switch {
  display: inline-flex; align-items: center; gap: var(--s4);
  margin-top: var(--s12); padding: var(--s4);
  border: 1px solid var(--line); border-radius: 999px;
  font-family: var(--mono); font-size: var(--t-micro); letter-spacing: 0.12em; text-transform: uppercase;
}
.lang-on, .lang-off { padding: var(--s4) var(--s12); border-radius: 999px; }
.lang-on { background: var(--ink); color: var(--paper); }
.lang-off { color: var(--ink-2); transition: background var(--fast) var(--ease), color var(--fast) var(--ease); }
.lang-off:hover { background: var(--sand); color: var(--ink); }
/* On the translation only. The original is a fact about the piece, not a
   disclaimer, so it is set like every other piece of metadata on the page. */
.lang-note { margin-top: var(--s12); font-family: var(--mono); font-size: var(--t-micro); letter-spacing: 0.04em; color: var(--ink-3); }

/* --s12 to match .lang-switch's margin-top, so the toggle sits evenly between
   the title and the photograph rather than drifting up toward the title. */
.article-figure { margin-top: var(--s12); }
.article-figure img {
  display: block; width: 100%; height: auto;
  border: 1px solid var(--line); border-radius: var(--radius-lg);
}
.article-figure figcaption {
  margin-top: var(--s12); font-family: var(--mono); font-size: var(--t-micro);
  letter-spacing: 0.04em; color: var(--ink-3); max-width: 60ch;
}
/* The credit is a link. It has to look like one without shouting over the
   photograph it sits under. */
.article-figure figcaption a { color: var(--ink-2); border-bottom: 1px solid var(--line-2); transition: color var(--fast) var(--ease), border-color var(--fast) var(--ease); }
.article-figure figcaption a:hover { color: var(--ink); border-color: var(--ink); }

.article-body { padding-block: var(--s40) var(--s96); }

/* The rail, where duna puts "On this page". Here it holds one line pulled out
   of the piece and set beside the body instead of inside it, so the reading
   column is never interrupted by its own best sentence. The column is kept
   whether or not a post fills it: the measure has to start in the same place
   on every page in the room, or the room stops feeling like one room. */
/* The divider runs the full height of the body, because it is a column rule,
   not a box around the quote. duna draws it as its own element for exactly
   this reason. So the rail itself stretches and holds the line, and the thing
   that sticks is the block inside it - which is also how duna does it: the
   heading scrolls away, the list stays. Do not move the sticky back up onto
   .article-rail; that shortens the rail to its content and the divider turns
   into a stub that slides down the page as you read. */
.article-grid { display: grid; grid-template-columns: 280px minmax(0, 1fr); gap: var(--s56); }
.article-rail { padding-right: var(--s40); border-right: 1px solid var(--line); }
.article-pull {
  position: sticky; top: calc(var(--nav-h) + var(--s40));
  border-left: 2px solid var(--peach); padding-left: var(--s20);
}
.article-pull p { color: var(--ink); font-size: var(--t-lead); line-height: 1.45; }
/* A post with no pull line gets its rail emitted as a literally empty element,
   with no whitespace inside, so :empty catches it and the divider goes. The
   line is there to separate two things; the column stays either way. */
.article-rail:empty { border-right: 0; }

/* Arabic runs in a naskh face at its own size. A du'a set in Figtree at body
   size is unreadable, and the fallback chain is what a phone with no Amiri
   lands on. Inline-block, not block, so the line keeps rtl glyph order without
   dragging itself to the right edge away from the transliteration under it. */
.ar {
  display: inline-block; font-family: 'Amiri', 'Geeza Pro', 'Noto Naskh Arabic', serif;
  font-size: 1.5em; line-height: 2; color: var(--ink);
}

/* Continue reading: the same .posts list as the room index, on the sand band
   so the article has an ending rather than just stopping. */
.continue { padding-block: var(--s72); background: var(--sand); border-top: 1px solid var(--line); }
.continue-head { font-family: var(--mono); font-size: var(--t-micro); letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3); font-weight: 400; }
.continue .posts { margin-top: var(--s24); }
.continue .post:hover { background: var(--paper); }
.continue .link-into { display: inline-block; margin-top: var(--s32); font-family: var(--mono); font-size: var(--t-small); border-bottom: 1px solid var(--ink); }

/* The wall close. A mono eyebrow is the right weight over text-only rows, but
   over three photographs it disappears, so this states the heading properly
   and puts the way back beside it rather than stranded under the last card. */
.continue-top { display: flex; align-items: center; justify-content: space-between; gap: var(--s24); }
.continue-title { font-size: var(--t-h3); font-weight: 600; letter-spacing: -0.032em; line-height: 1.15; }
.continue.is-wall .posts { margin-top: var(--s40); }
/* The row layout washes a hovered row in paper. A card is not a row, and the
   wash would draw a box that is not there. */
.continue.is-wall .post:hover { background: none; }

/* -- 7b. PEOPLE (duna-derived: face, name, role, then the bio) -------------- */
/* duna runs two of these because it has two founders. This runs three because
   one person has three tracks, so the SAME portrait sits in all three cards.
   That repetition is the argument, not an oversight - one hand, three names.
   White card on the sand band, hairline not shadow, per the structure rule. */
.people { margin-top: var(--s56); display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s24); }
.person { border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--paper); padding: var(--s32); }
.person-head { display: flex; align-items: center; gap: var(--s16); }
.person-photo {
  flex: 0 0 auto; width: 56px; height: 56px; border-radius: 10px;
  object-fit: cover; object-position: 62% 30%; filter: grayscale(1);
  border: 1px solid var(--line);
}
.person-name { font-size: var(--t-h3); font-weight: 600; letter-spacing: -0.032em; line-height: 1.1; }
.person-role { display: block; margin-top: var(--s4); font-family: var(--mono); font-size: var(--t-micro); letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3); }
.person-bio { margin-top: var(--s32); color: var(--ink-2); font-size: var(--t-body); line-height: 1.7; }

/* -- 8. CONTACT / FOOTER ---------------------------------------------------- */
.contact { position: relative; padding-block: var(--s128) var(--s96); border-top: 1px solid var(--line); text-align: center; overflow: hidden; }
.contact::before {
  content: ''; position: absolute; left: 50%; bottom: -320px; width: 900px; height: 620px; margin-left: -450px;
  border-radius: 50%; background: radial-gradient(closest-side, rgba(251, 201, 147, 0.5), rgba(242, 179, 188, 0.22) 55%, transparent 78%);
  pointer-events: none;
}
.contact .shell { position: relative; z-index: 1; }
.contact h2 { font-size: var(--t-h2); margin-top: var(--s16); }
.contact-lead { max-width: 46ch; margin: var(--s20) auto 0; color: var(--ink-2); font-size: var(--t-lead); line-height: 1.5; }
.contact-cta { display: flex; gap: var(--s12); justify-content: center; margin-top: var(--s32); flex-wrap: wrap; }

.foot { margin-top: var(--s128); border-top: 1px solid var(--line); padding-top: var(--s32); display: flex; align-items: center; gap: var(--s24); flex-wrap: wrap; font-size: var(--t-small); color: var(--ink-3); text-align: left; }
.foot-links { display: flex; gap: var(--s24); margin-left: auto; flex-wrap: wrap; }
.foot-links a { transition: color var(--fast) var(--ease); }
.foot-links a:hover { color: var(--ink); }

/* Interior pages close on the footer alone, with no contact band above it, so
   the .foot top margin would double up on the band padding. */
.page-foot { padding-bottom: var(--s56); }
.page-foot .foot { margin-top: 0; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* -- 9. RESPONSIVE ------------------------------------------------------- */
@media (max-width: 1080px) {
  
  
  
  .people { grid-template-columns: repeat(2, 1fr); }
  .article-grid { grid-template-columns: 220px minmax(0, 1fr); gap: var(--s40); }
  .article-rail { padding-right: var(--s32); }
  .posts.is-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s40) var(--s24); }
}
@media (max-width: 900px) {
  :root { --gutter: var(--s20); --nav-h: 66px; }
  .nav-menu, .nav-actions .btn-outline { display: none; }
  .nav-toggle { display: inline-flex; }
  .nav-inner { grid-template-columns: 1fr auto; }
  .nav-menu.is-open {
    display: flex; position: absolute; top: var(--nav-h); left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: 2px; padding: var(--s12);
    background: rgba(253, 251, 247, 0.97); backdrop-filter: blur(20px) saturate(180%);
    -webkit-backdrop-filter: blur(20px) saturate(180%); border-bottom: 1px solid var(--line);
  }
  .nav-menu.is-open .nav-link { height: 48px; justify-content: flex-start; }

  /* No hover on a phone, so the dropdown stops being a dropdown and becomes an
     indented list under its parent. Hiding it here made every sub-item
     unreachable on mobile. */
  .nav-menu.is-open .nav-panel {
    position: static; display: grid; grid-template-columns: 1fr; width: auto;
    margin: 0 0 var(--s8); padding: 0 0 0 var(--s16);
    border: 0; border-radius: 0; background: transparent;
    backdrop-filter: none; -webkit-backdrop-filter: none; box-shadow: none;
    opacity: 1; visibility: visible; transform: none;
  }
  .nav-menu.is-open .nav-panel::before { display: none; }
  .nav-menu.is-open .panel-link {
    padding: var(--s12) var(--s8); opacity: 1; transform: none; transition-delay: 0s;
  }
  .nav-menu.is-open .panel-link { color: var(--ink); }
  .nav-menu.is-open .panel-link:hover { background: var(--sand); }
  .nav-menu.is-open .panel-link span { display: none; }
  .nav-menu.is-open .caret { display: none; }
  .hero { min-height: 92svh; }
  
  
  
  
  .contact { padding-block: var(--s72); }
  .foot { margin-top: var(--s72); }
  .page-hero { padding-block: var(--s72) var(--s56); }
  .band { padding-block: var(--s72); }
  .band.is-sand + .band { padding-top: var(--s72); }
  .article-head { padding-block: var(--s8) 0; }
  .article-head h1 { max-width: none; }
  .article-figure { margin-top: var(--s8); }
  .article-body { padding-block: var(--s32) var(--s72); }
  .post { grid-template-columns: 200px minmax(0, 1fr); gap: var(--s24); }
  /* The rail stops being a rail and becomes the opening line, above the body.
     Sticky is dropped with it: on a phone it would sit on top of the reading. */
  .article-grid { grid-template-columns: 1fr; gap: var(--s40); }
  .article-rail { padding-right: 0; border-right: 0; }
  .article-pull { position: static; }
  .continue { padding-block: var(--s56); }

  /* Five columns crush below ~700px. Two up, and the fifth takes the full
     width rather than sitting alone in a half-width cell. */
  .people { grid-template-columns: 1fr; }
  .person { padding: var(--s24); }
  
  
  
  
}
@media (max-width: 620px) {
  
  
  .btn { height: 48px; width: 100%; }
  .hero-cta, .contact-cta { flex-direction: column; }
  .row { grid-template-columns: 1fr; gap: var(--s4); }
  /* The photograph stops being a column and sits above the copy. */
  .post { grid-template-columns: 1fr; gap: var(--s16); }
  .posts.is-grid { grid-template-columns: 1fr; gap: var(--s40); }
  .posts.is-grid .post-thumb { border-radius: var(--radius); }
  /* The button goes full-width at this size, so it cannot sit beside the head. */
  .continue-top { flex-direction: column; align-items: flex-start; gap: var(--s20); }
  .article-figure img { border-radius: var(--radius); }
  
  
  .contact-links { flex-direction: column; gap: var(--s16); }
}

/* -- 10. MOTION ------------------------------------------------------------ */

/* -- 11. HOME ------------------------------------------------------------- */
/* The homepage-only blocks. These used to live in a <style> tag inside
   index.html alongside a full second copy of everything above, which is how
   the nav on the homepage quietly fell a version behind the nav everywhere
   else. One stylesheet now, so that cannot happen again. */
.pill-badge {display: inline-flex; align-items: center; gap: var(--s8); padding: var(--s8) var(--s8) var(--s8) var(--s16); border-radius: 999px; background: rgba(58, 44, 38, 0.5); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); color: #FFF; font-size: var(--t-small); font-weight: 500; transition: background var(--fast) var(--ease), transform var(--fast) var(--ease);}
.pill-badge:hover {background: rgba(58, 44, 38, 0.72); transform: translateY(-1px);}
.pill-badge .arrow {opacity: 0.8;}
.latest {padding-block: var(--s56) var(--s72); background: var(--sand); border-top: 1px solid var(--line);}
.latest .shell {max-width: 1000px;}
.latest h2 {font-size: var(--t-h2); margin-top: var(--s16); max-width: 24ch;}
.latest-lead {margin-top: var(--s12); color: var(--ink-2); font-size: var(--t-lead); line-height: 1.5; max-width: 52ch;}
.latest-grid {margin-top: var(--s32); display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--s40); align-items: start;}
.latest-rail {display: grid; gap: 2px;}
.latest-row {appearance: none; -webkit-appearance: none; position: relative; display: block; width: 100%; text-align: left; cursor: pointer; margin: 0; padding: var(--s12) var(--s16) var(--s12) var(--s32); font-family: inherit; color: inherit; background: transparent; border: 0; border-left: 2px solid transparent; border-radius: var(--radius); transition: background var(--fast) var(--ease);}
.latest-row::before {content: ''; position: absolute; left: var(--s16); top: calc(var(--s12) + 0.55em); width: 5px; height: 5px; border-radius: 50%; background: var(--sage); transition: transform var(--fast) var(--ease);}
.latest-row:hover {background: var(--paper);}
.latest-row.is-open {background: var(--paper); border-left-color: var(--sage); cursor: default;}
.latest-row.is-open::before {transform: scale(1.4);}
.latest-row-room {display: block; font-family: var(--mono); font-size: var(--t-micro); letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3);}
.latest-row-title {display: none; margin-top: var(--s4); font-size: 1.0625rem; font-weight: 600; letter-spacing: -0.024em; line-height: 1.3;}
.latest-row.is-open .latest-row-title {display: block;}
.latest-panels {display: grid;}
.latest-panel {grid-area: 1 / 1;}
.latest-panel[hidden] {display: none;}
.latest-panel-link {display: block; padding: var(--s12); background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg); transition: border-color var(--fast) var(--ease), box-shadow var(--fast) var(--ease);}
.latest-panel-link:hover {border-color: var(--sage); box-shadow: 0 18px 40px -30px rgba(26, 25, 23, 0.55);}
.latest-panel-link img {width: 100%; height: auto; aspect-ratio: 2 / 1; object-fit: cover; border-radius: var(--radius);}
.latest-panel-copy {display: block; padding: var(--s16) var(--s4) var(--s4);}
.latest-panel-room {display: block; font-family: var(--mono); font-size: var(--t-micro); letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3);}
.latest-panel-title {display: block; margin-top: var(--s8); font-size: clamp(1.25rem, 1.7vw, 1.5rem); font-weight: 600; letter-spacing: -0.032em; line-height: 1.2;}
.latest-panel-stand {display: block; margin-top: var(--s8); color: var(--ink-2); font-size: var(--t-small); line-height: 1.55; max-width: 52ch;}
@media (max-width: 900px) {
  .latest {padding-block: var(--s56) var(--s72);}
  .latest-grid {grid-template-columns: 1fr; row-gap: var(--s40);}
  .latest-panels {order: -1;}
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; transition-delay: 0s !important; }
}
