/* MingPath demo — editorial redesign.
   Warm photographic ground behind a dark scrim · paper ONLY for the chart card
   and the report-preview pages · cinnabar for the day master ALONE · a bronze
   accent for buttons, kept distinct from cinnabar so cinnabar keeps one
   meaning · Spectral display · Inter Tight body · IBM Plex Mono labels and
   chart data · a hand-drawn, imperfect line-icon system, used sparingly. */

:root{
  --ink:#1B140F;
  --ink-2:rgba(30,18,12,.46);
  --ink-3:rgba(30,18,12,.62);
  --paper:#E7E0D2;
  --paper-2:#D9D1C0;
  --type:#EFE2D3;
  --type-dim:#BBA187;
  --cinnabar:#B23A2E;
  --cinnabar-lift:#C9584A;
  --rule:rgba(239,226,211,.16);
  --dim-warm:rgb(140,122,105);      /* fineprint / footer / mono captions */

  /* THE READING MEASURE. 640px sits inside the 600–680px band, so on a wide
     monitor body text never runs the full width. Prose is pinned to this at
     EVERY width and never grows — past roughly 70 characters a line, reading
     gets measurably harder. Phone and tablet simply run narrower. */
  --measure:40rem;

  /* THE COLUMN. What the page's blocks span on a large screen — every block,
     so they all share one left and right edge. Equal to the measure below
     1180px, so nothing changes on phone or tablet. */
  --shell:40rem;

  --gutter:1.35rem;
  --plate:url("bg-texture.jpg");   /* the PHONE plate; desktop swaps it below */
}
@media (min-width:1180px){ :root{ --shell:58rem; } }   /* 928px */
@media (min-width:1600px){ :root{ --shell:64rem; } }   /* 1024px */

*{box-sizing:border-box;margin:0;padding:0}
/*  [hidden] MUST WIN.
    The browser hides `[hidden]` with `display:none` from its own stylesheet,
    which ANY author rule setting `display` outranks. `.btn{display:inline-block}`
    and `form.enquiry{display:grid}` both did exactly that, so the 2027 enquiry
    form rendered open before anyone clicked the CTA and the CTA stayed on
    screen after being used. One declaration fixes the whole class of bug, and
    it must stay above the rules that set `display`. */
[hidden]{display:none !important}

html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;overflow-x:hidden}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}

body{
  /*  Flat ink only. The photographic plate is painted by .scrim, NOT here --
      see the note on that rule. */
  background:var(--ink);
  color:var(--type);
  font-family:'Inter Tight',system-ui,-apple-system,'Segoe UI',sans-serif;
  font-weight:300;
  font-size:17px;
  line-height:1.65;
  letter-spacing:.005em;
  padding:0 var(--gutter) 4.5rem;
  min-height:100vh;
  overflow-x:hidden;
}

/*  THE WIDE PLATE, desktop only.

    `cover` scales the background to fill the viewport, so a 736px-wide plate on
    a 1440px monitor is being blown up 2x and the weave breaks into visible
    pixels -- which is the artefact Daniel photographed. This is a resolution
    problem, not a styling one, so the fix is a second file at the right size
    rather than any change to how it is drawn.

    1672x941 is exactly 16:9, so on a 1920x1080 screen both axes need the same
    1.15x and nothing is cropped unevenly.

    The switch is at 1024px on purpose. Below it the portrait plate is scaling
    by well under 1.4x and still looks clean, and phones and portrait tablets
    keep the background they already have -- untouched, as asked. */
@media (min-width:1024px){
  :root{--plate:url("bg-texture-wide.jpg")}
}
/* A fixed dark scrim over the photograph, so type stays legible everywhere.
   Sibling of .wrap, not a wrapper — never intercepts clicks. */
/*  THE PLATE LIVES HERE, not on `body`.

    It used to be `background-attachment:fixed` on the body. iOS Safari does not
    honour that the way every other browser does: it paints the plate once
    against the document rather than the viewport, so on a page taller than the
    screen the texture ran out partway down and everything below the button fell
    back to flat ink. That is the black band Daniel photographed on his phone.

    .scrim is already `position:fixed`, so it covers the viewport by definition
    and needs no attachment trick at all. The gradient stays the top layer and
    the plate sits under it, which is exactly the order the two had before. */
.scrim{
  position:fixed;inset:0;z-index:0;pointer-events:none;
  background:
    linear-gradient(rgba(15,9,6,.35),rgba(15,9,6,.55) 40%,rgba(15,9,6,.7)),
    var(--plate) center center/cover no-repeat;
}
.wrap{max-width:var(--measure);margin:0 auto;position:relative;z-index:1}

/* A soft vignette toward the true screen edges, so the eye settles on the
   column instead of drifting into flat corners. No hairline, no frame: an
   earlier attempt drew a 1px rule at each edge of the column and it read as
   an accidental border rather than a drawn boundary. Removed. */
@media (min-width:720px){
  .stage{
    position:fixed;inset:0;z-index:0;pointer-events:none;
    background:linear-gradient(90deg,
      rgba(10,6,4,.4) 0,
      rgba(10,6,4,.1) calc(50% - var(--shell)/2 - 7rem),
      rgba(10,6,4,0) calc(50% - var(--shell)/2),
      rgba(10,6,4,0) calc(50% + var(--shell)/2),
      rgba(10,6,4,.1) calc(50% + var(--shell)/2 + 7rem),
      rgba(10,6,4,.4) 100%);
  }
}

/* ---------- HOW THE PAGE USES A WIDE MONITOR ----------
   Two widths, and only two:

     --shell    every BLOCK spans it, so all block edges line up
     --measure  every run of PROSE is capped at it, left-aligned inside

   Pinning everything to the measure left two 440px voids down the sides of a
   1500px screen. Widening only the diagrams left the page alternating between
   two widths, which read as misalignment. Blocks share one edge; text keeps a
   readable line length inside them. */
@media (min-width:1180px){
  /* ONE EDGE FOR THE WHOLE PAGE.
     An earlier attempt let only the chart card and the rhythm section widen
     while every text block stayed at the measure. That alternated 1024 / 640
     / 1024 down the page and read as misalignment, not as rhythm. Every
     block now shares the same left and right edge: the card, the 2026 panel,
     each finding, the match question, the rhythm section. */
  .wrap{max-width:var(--shell)}

  /* the card and the rhythm section used to break OUT of a narrower wrap;
     they now simply fill it */
  .card,.rhythm{width:auto;margin-left:0;margin-right:0}

  /* PROSE STAYS READABLE INSIDE THAT WIDTH.
     Containers span the full column so their edges line up; running text is
     capped at the measure and left-aligned within them, so line length never
     grows past a comfortable ~70 characters however wide the monitor is.
     Alignment is carried by the block edges; readability by the text cap. */
  .card .note,
  .hinge .wrapper-lines,.hinge .signature,.hinge h2,.hinge > p,
  .reality-row .rr-text,
  .contact-step > p,.contact-step .step-headline,.contact-step .consequence,
  .checkline,
  .finding > h2,.finding > p,
  details.deeper .inner > p,details.deeper .inner > h3,
  .match .q,
  .rhythm-closed{
    max-width:var(--measure);
    margin-left:0;
    margin-right:0;
  }

  /* The margin figures: every finding AND the 2026 panel, identical.
     `.hinge .hinge-fig`, not `.hinge-fig`: the base display:none is declared
     further down the file, so a bare class here would lose on source order. */
  .hinge .hinge-fig,
  .finding .fig-margin{
    display:block;position:absolute;
    width:180px;color:var(--type-dim);opacity:.45;pointer-events:none;
  }
  .hinge .hinge-fig{top:2.4rem;right:2.4rem}
  .finding .fig-margin{top:3rem;right:2.4rem}
  /* the heading is capped at the measure out here, so it cannot reach the
     figure and needs no padding */
  .finding > h2{padding-right:0}

  /* six month cards read better as two rows of three once there is room */
  .rhythm .months{grid-template-columns:repeat(3,1fr)}

  /* The landing form is the one block that should NOT fill the column --
     inputs stretched across a monitor are worse, not better. It stays at the
     measure, centred, and the page gets its presence from the headline
     instead, which is otherwise capped at a size chosen for a phone. */
  form.birth{max-width:var(--measure);margin-left:auto;margin-right:auto}
  .masthead h1{font-size:clamp(2.1rem,8.4vw,3.6rem)}
}
.mono{font-family:'IBM Plex Mono',ui-monospace,SFMono-Regular,Menlo,monospace}
.serif{font-family:Spectral,Georgia,'Times New Roman',serif}

a{color:var(--cinnabar-lift)}
a:hover{color:var(--type)}
a:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible{
  outline:2px solid var(--cinnabar-lift);outline-offset:3px;
}

/* ---------- masthead ---------- */
.masthead{padding:2.1rem 0 1.4rem;text-align:center}
.mark{
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.66rem;letter-spacing:.42em;text-transform:uppercase;
  color:var(--type-dim);
}
.masthead h1{
  font-family:Spectral,Georgia,serif;font-weight:200;
  font-size:clamp(2.1rem,8.4vw,3.1rem);
  line-height:1.08;letter-spacing:-.015em;
  margin:.85rem 0 .55rem;
}
.masthead .sub{
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.7rem;letter-spacing:.12em;color:var(--type-dim);
}
.partner-line{
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.62rem;letter-spacing:.2em;text-transform:uppercase;
  color:var(--type-dim);text-align:center;
  padding:1.1rem 0 0;
}

/* ---------- the soul mark: the landing form's one animated glyph ----------
   Decorative only — never a claim about the chart.

   The supplied artwork is dark ink on OPAQUE PAPER, which would render as a
   pale disc on this page's dark ground. `scripts/build_soul_icon.py` converts
   each layer to an alpha mask, so the ink is painted with `currentColor` and
   inherits the page's own token instead of the artwork's near-black.

   Sequence, per the handoff: the ring draws itself in over 1.6s, a beat, then
   the interior and flame fade up and settle into an unsynced breathing loop.

   Every distance is expressed against --soul-size rather than the handoff's
   raw pixels, which were authored for a 270px icon. At this scale a literal
   `translateY(-2px)` would be a seventh of the whole mark. */
/*  THE MARK BAND.

    The gap above the ring and the gap below it must read as ONE value. Three
    things were quietly fighting that, and all three are handled here:

    1.  The band used to be padded well beyond the drawing, so both gaps
        inherited that padding. It now hugs the ink exactly -- its height IS
        the ring's height -- so the gaps are the margins below and nothing else.
    2.  The supplied artwork is not centred in its own file: the ring sits 27.2%
        from the top of the canvas but 32.5% from the bottom. `--soul-lift`
        cancels that, so the RING is centred in the band rather than the box.
    3.  `.masthead` spaces itself with padding that grows at every breakpoint,
        which is why the top gap was 40.8px on a phone and 56.8px on a laptop
        while the bottom stayed at 62.7px. The landing masthead gives that up
        and the gap is set here instead, once, for every width.

    --mark-gap is the single value for BOTH sides. The two offsets subtract the
    text's own leading (2.48px under the subline, 1px above the NAME label) so
    that the gap is measured ink-to-ink, which is what the eye actually sees. */
/*  On :root, not on .tiny-mark: the form is the band's SIBLING, not its child,
    so a value declared on the band would not reach it and the lower gap would
    silently fall back to zero. */
:root{--mark-gap:44px}
.masthead.landing{padding-bottom:0}
.tiny-mark{
  --soul-size:260px;
  --ink-ratio:.403;        /* ring height as a share of the box; from the PNG */
  --soul-lift:.0265em;     /* re-centres the off-centre artwork in the band */
  display:flex;align-items:center;justify-content:center;
  height:calc(var(--soul-size) * var(--ink-ratio));
  margin:calc(var(--mark-gap) - 2.48px) 0 0;
}
form.birth{margin-top:calc(var(--mark-gap) - 1px)}
.soul{
  /*  THE ONE KNOB. Everything below is in em against font-size, so the whole
      mark -- stroke weight, flame travel, glow -- scales from this line.
      It is set at logo scale deliberately: at 44px the mark disappeared into
      the photograph's grain and read as a smudge rather than a drawing.

      THIS IS THE BOX, NOT THE DRAWING. The handoff artwork sits in a large
      transparent margin -- the ring covers about 40% of its canvas -- so the
      ink a reader actually sees is roughly two fifths of this number. That is
      why 260px here is not 260px on screen, and why the box may exceed the
      9.4rem band below without anything colliding: the overflow is empty
      alpha. `tests/demo/test_soul_mark.py` measures the real ink extent out of
      the PNGs and checks the --ink-ratio above is honest about it.

      The value itself is declared on .tiny-mark and inherits down, so the band
      height can be derived from it. */
  position:relative;display:block;
  transform:translateY(var(--soul-lift));
  width:var(--soul-size);height:var(--soul-size);
  font-size:var(--soul-size);          /* so em units below track the size */
  /*  Full ink, not --type-dim. The background here is a NOISY photograph, and
      a dim hairline on grain is the one thing that will not survive it. The
      shadow does the rest: it separates the strokes from the texture without
      putting a box or a plate behind the mark. */
  color:var(--type);
  filter:drop-shadow(0 2px 12px rgba(10,6,4,.75));
}
.soul-layer{
  position:absolute;inset:0;background:currentColor;
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  -webkit-mask-size:contain;mask-size:contain;
  -webkit-mask-position:center;mask-position:center;
}
.soul-rest{-webkit-mask-image:url("soul-rest.png");mask-image:url("soul-rest.png")}
.soul-ring{-webkit-mask-image:url("soul-ring.png");mask-image:url("soul-ring.png")}
.soul-flame{
  -webkit-mask-image:url("soul-flame.png");mask-image:url("soul-flame.png");
  /* the flame's base point in the source canvas, so the wave pivots from the
     base like a real flame rather than the image centre */
  transform-origin:50.2% 58.5%;
}
/* The ring's draw-in is a conic wipe on a WRAPPER, so the layer itself keeps
   its own shape mask. Compositing two masks on one element needs
   mask-composite, which is still uneven across browsers. */
.soul-ring-clip{
  position:absolute;inset:0;
  -webkit-mask-image:conic-gradient(from -90deg,#000 0deg,#000 var(--sweep),
    transparent var(--sweep),transparent 360deg);
  mask-image:conic-gradient(from -90deg,#000 0deg,#000 var(--sweep),
    transparent var(--sweep),transparent 360deg);
  animation:soul-ring-draw 1.6s cubic-bezier(.65,0,.35,1) forwards;
}
.soul-glow{
  position:absolute;left:44%;top:42%;width:18%;height:24%;border-radius:50%;
  background:radial-gradient(closest-side,rgba(196,138,74,.35),rgba(196,138,74,0));
  filter:blur(.034em);transform-origin:50% 80%;
}
.soul-rest{animation:soul-fade-in .55s ease-out 1.9s both}
.soul-flame{animation:soul-fade-in .6s ease-out 1.95s both,
                      soul-flame-wave 5.5s ease-in-out 2.55s infinite}
.soul-glow{animation:soul-fade-in .6s ease-out 1.95s both,
                     soul-glow-breathe 6s ease-in-out 2.55s infinite}

/*  THE STRIKE -- phones and tablets only, once, never on desktop.

    The candle coming up should feel like it was struck, so the mark gives a
    single short shudder at the exact moment the flame and glow fade in
    (1.95s, the same delay those two carry) and a warm flare blooms out of the
    wick with it. One event, not two.

    The shudder is on .tiny-mark rather than .soul because .soul already
    carries `translateY(var(--soul-lift))` to centre the artwork, and animating
    transform there would fight that correction and drop the mark out of its
    band. .tiny-mark has no transform of its own, and being a fixed-height
    flex band, moving it cannot disturb anything around it.

    This is a VISUAL vibration. Real haptics are not available here: iOS Safari
    does not implement the Vibration API at all, and where it does exist it
    needs a user gesture, which an animation that runs on page load does not
    have. */
@media (max-width:1023px){
  .tiny-mark{
    animation:mark-strike .46s cubic-bezier(.36,.07,.19,.97) 1.95s both;
  }
  /*  The flare. Same origin and size as .soul-glow, so it blooms out of the
      wick rather than the middle of the ring. */
  .soul::after{
    content:"";position:absolute;left:44%;top:42%;width:18%;height:24%;
    border-radius:50%;pointer-events:none;
    background:radial-gradient(closest-side,
      rgba(255,216,158,.85),rgba(255,184,110,.28) 55%,rgba(255,184,110,0));
    opacity:0;
    animation:soul-flare .6s ease-out 1.95s both;
  }
}
@keyframes mark-strike{
  0%   {transform:translate3d(0,0,0)}
  12%  {transform:translate3d(-1.6px,.8px,0) rotate(-.5deg)}
  26%  {transform:translate3d(1.4px,-1px,0) rotate(.45deg)}
  42%  {transform:translate3d(-1.1px,-.5px,0) rotate(-.3deg)}
  58%  {transform:translate3d(.9px,.6px,0) rotate(.25deg)}
  74%  {transform:translate3d(-.5px,-.3px,0) rotate(-.12deg)}
  88%  {transform:translate3d(.3px,.2px,0) rotate(.06deg)}
  100% {transform:translate3d(0,0,0)}
}
@keyframes soul-flare{
  0%   {opacity:0;transform:scale(.35)}
  16%  {opacity:1;transform:scale(1.45)}
  46%  {opacity:.42;transform:scale(2.1)}
  100% {opacity:0;transform:scale(2.9)}
}

@property --sweep{syntax:'<angle>';inherits:false;initial-value:0deg}
@keyframes soul-ring-draw{from{--sweep:0deg}to{--sweep:360deg}}
@keyframes soul-fade-in{from{opacity:0}to{opacity:1}}
@keyframes soul-flame-wave{
  0%  {transform:translateY(0)          scaleY(1)     skewX(0deg)}
  22% {transform:translateY(-.0056em)   scaleY(1.03)  skewX(.6deg)}
  48% {transform:translateY(-.0019em)   scaleY(.985)  skewX(-.8deg)}
  70% {transform:translateY(-.0074em)   scaleY(1.045) skewX(.4deg)}
  100%{transform:translateY(0)          scaleY(1)     skewX(0deg)}
}
@keyframes soul-glow-breathe{
  0%,100%{opacity:.08;transform:scale(1)}
  50%    {opacity:.17;transform:scale(1.06)}
}
/* Reduced motion: the finished mark, fully assembled, with no motion at all. */
@media (prefers-reduced-motion:reduce){
  .soul-ring-clip{-webkit-mask-image:none!important;mask-image:none!important;
    animation:none!important}
  .soul-rest,.soul-flame,.soul-glow{
    animation:none!important;opacity:1!important;transform:none!important}
}

/* ---------- SCREEN 1 — the form is the landing page ---------- */
.lede{
  font-family:Spectral,Georgia,serif;font-weight:300;
  font-size:clamp(1.15rem,4.6vw,1.35rem);line-height:1.45;
  text-align:center;margin:0 auto 2rem;max-width:24rem;
}
.lede span{display:block;color:var(--type-dim)}

form.birth{display:grid;gap:1rem}
.row{display:grid;gap:1rem}
@media (min-width:480px){.row.two{grid-template-columns:1fr 1fr}}

label{
  display:block;
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.6rem;letter-spacing:.24em;text-transform:uppercase;
  color:var(--type-dim);margin-bottom:.4rem;
}
input,select{
  width:100%;
  background:var(--ink-2);
  backdrop-filter:blur(6px);
  border:1px solid var(--rule);
  border-radius:2px;
  color:var(--type);
  font-family:'Inter Tight',system-ui,sans-serif;
  font-size:1rem;font-weight:300;
  padding:.85rem .9rem;
  min-height:48px;                    /* touch target */
}
/*  iOS renders date and time as NATIVE controls once they hold a value, and
    those controls bring their own intrinsic width and centred text. Inside a
    grid the item's default `min-width:auto` then refuses to shrink below that
    width, so the two fields pushed past the column edge while the plain text
    and select fields beside them sat correctly -- which is exactly the
    mismatch Daniel photographed.

    `appearance:none` opts them out of the native metrics, `min-width:0` lets
    the grid shrink them, and `text-align:left` puts the value where every
    other field in the form puts it. The picker still opens on tap.

    NOTE: Playwright's WebKit does not render the native iOS controls, so this
    could not be reproduced or confirmed on this machine -- it needs a look on
    a real iPhone. */
input[type="date"],input[type="time"]{
  -webkit-appearance:none;appearance:none;
  min-width:0;max-width:100%;
  text-align:left;
}
/*  Grid and flex items default to min-width:auto, which is what allowed an
    over-wide control to push its whole column out. */
form.birth > div,.row > div{min-width:0}
input,select{max-width:100%}

input::placeholder{color:var(--dim-warm)}
input:focus,select:focus{border-color:var(--cinnabar-lift)}
input[aria-invalid="true"]{border-color:var(--cinnabar)}
.field-error{
  color:var(--cinnabar-lift);font-size:.82rem;line-height:1.45;margin-top:.45rem;
}
.hint{color:var(--type-dim);font-size:.8rem;margin-top:.4rem}

/* Bronze/ochre — deliberately NOT cinnabar, so cinnabar keeps one meaning:
   the day master alone. */
.btn{
  display:inline-block;width:100%;text-align:center;
  background:#A9754F;color:#241811;
  font-family:'Inter Tight',system-ui,sans-serif;font-weight:500;
  font-size:.95rem;letter-spacing:.03em;
  padding:1rem 2.1rem;border:0;border-radius:2px;text-decoration:none;
  cursor:pointer;min-height:52px;
  transition:background .18s ease;
}
.btn:hover,.btn:focus-visible{background:#BF8B63}
.btn[disabled]{opacity:.45;cursor:default}
.btn.ghost{
  background:transparent;color:var(--type);
  border:1px solid var(--rule);
}
.btn.ghost:hover{background:var(--ink-2)}
.fineprint{
  margin-top:1.1rem;font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.62rem;letter-spacing:.09em;color:var(--dim-warm);line-height:1.8;
  text-align:center;
}

/* ---------- the chart card: the ONLY paper surface (with the report pages) ---------- */
.card{
  background:var(--paper);
  color:#1A2029;
  border-radius:2px;
  padding:1.5rem 1.15rem 1.75rem;
  box-shadow:0 22px 50px -18px rgba(0,0,0,.65);
  position:relative;
}
.card .cap{
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.6rem;letter-spacing:.3em;text-transform:uppercase;
  color:#6B6255;text-align:center;margin-bottom:1.15rem;
}
.card table{width:100%;border-collapse:collapse;table-layout:fixed}
.card th{
  font-family:'IBM Plex Mono',ui-monospace,monospace;font-weight:400;
  font-size:.58rem;letter-spacing:.2em;text-transform:uppercase;
  color:#847A6B;padding-bottom:.55rem;
}
.card td{
  text-align:center;
  font-family:Spectral,Georgia,serif;font-weight:300;
  font-size:clamp(1.75rem,9.4vw,2.4rem);
  line-height:1.25;padding:.15rem 0 .45rem;
}
.card td.rowlab,.card th.rowlab{
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.58rem;letter-spacing:.2em;text-transform:uppercase;
  color:#847A6B;text-align:left;width:3.6rem;
}
/* CINNABAR IS THE DAY MASTER'S ALONE. Nothing else on the card takes it. */
.card td.dm{color:var(--cinnabar);position:relative}
.card td.dm::after{
  content:"";position:absolute;left:50%;bottom:.12rem;
  width:1.7rem;height:1px;background:var(--cinnabar);
  transform:translateX(-50%);opacity:.55;
}
.card .note{
  margin-top:1.3rem;padding-top:1rem;border-top:1px solid rgba(26,32,41,.16);
  font-size:.86rem;line-height:1.6;color:#4A4438;
}
.card .note b{color:var(--cinnabar);font-weight:500}

/* the thread: the reading hangs from the day master */
.thread{height:3.4rem;display:flex;justify-content:center}
.thread span{width:1px;height:100%;background:linear-gradient(var(--cinnabar),var(--rule))}

/* ---------- sections ---------- */
section{padding-bottom:2.9rem}
.eyebrow{
  display:flex;align-items:center;gap:.85rem;
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.62rem;letter-spacing:.26em;text-transform:uppercase;
  color:var(--type-dim);margin-bottom:1.15rem;
}
.eyebrow::after{content:"";flex:1;height:1px;background:var(--rule)}
h2{
  font-family:Spectral,Georgia,serif;font-weight:300;
  font-size:clamp(1.5rem,5.9vw,2rem);
  line-height:1.2;letter-spacing:-.01em;margin-bottom:1.1rem;
}
h3{
  font-family:'Inter Tight',system-ui,sans-serif;font-weight:500;
  font-size:.79rem;letter-spacing:.09em;text-transform:uppercase;
  color:var(--type-dim);margin:1.7rem 0 .5rem;
}
p{margin-bottom:1rem}
p:last-child{margin-bottom:0}

/* ---------- the 2026 hinge ---------- */
.hinge{
  background:var(--ink-2);
  backdrop-filter:blur(6px);
  border-left:2px solid var(--cinnabar);
  border-radius:0 2px 2px 0;
  padding:1.7rem 1.3rem;
  position:relative;
}
/* The panel spans the full column while its prose is capped, which leaves
   space on the right at desktop widths. The loop motif fills it -- the same
   figure the teaser already uses beside this block's text. Hidden below
   1180px, where the panel and the prose are the same width and there is no
   space to fill. */
.hinge-fig{display:none}
.hinge .eyebrow{color:var(--cinnabar-lift)}
.hinge .eyebrow::after{background:rgba(178,58,46,.4)}
.wrapper-lines{
  font-family:Spectral,Georgia,serif;font-weight:300;font-style:italic;
  font-size:1rem;line-height:1.55;color:var(--type-dim);margin-bottom:1.4rem;
}
.wrapper-lines span{display:block}
/* Editorial pull-quote treatment: italic serif, not a data-label. */
.signature{
  font-family:Spectral,Georgia,serif;font-weight:300;font-style:italic;
  font-size:clamp(1.5rem,6.4vw,2.05rem);
  line-height:1.3;letter-spacing:-.005em;
  color:var(--type);margin:.6rem 0 1.7rem;
  text-transform:none;
}
.hinge h2{font-size:clamp(1.4rem,5.6vw,1.8rem)}

/* the teaser: editorial text beside one hand-drawn metaphor. Stacks on
   phone, sits side by side from tablet up. */
.reality-row{display:flex;flex-direction:column;gap:1.3rem}
.reality-row .rr-fig{align-self:center;width:110px;opacity:.9;color:var(--type-dim)}
@media (min-width:720px){
  .reality-row{flex-direction:row;align-items:flex-start;gap:2.2rem}
  .reality-row .rr-text{flex:1}
  .reality-row .rr-fig{flex:0 0 140px;width:140px;align-self:flex-start;margin-top:.2rem}
}

/* the teaser fade: cut EARLY, mid-recognition */
.fade{position:relative;margin-top:1rem}
.fade p{
  color:var(--type-dim);
  -webkit-mask-image:linear-gradient(180deg,#000 0%,transparent 92%);
  mask-image:linear-gradient(180deg,#000 0%,transparent 92%);
  filter:blur(.2px);
}
.fade::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,rgba(28,40,54,0) 0%,var(--ink-2) 96%);
}

/* ---------- the gate ---------- */
.gate{
  border-top:1px solid var(--rule);
  margin-top:2.4rem;padding-top:2.2rem;
}
.gate .line{
  font-family:Spectral,Georgia,serif;font-weight:300;
  font-size:clamp(1.25rem,5vw,1.6rem);line-height:1.3;margin-bottom:.35rem;
}
.gate .line.dim{color:var(--type-dim);margin-bottom:1.5rem}
.consent{
  display:flex;gap:.7rem;align-items:flex-start;
  margin:1.1rem 0 1.3rem;
}
.consent input{width:20px;height:20px;min-height:20px;flex:0 0 auto;margin-top:.15rem;accent-color:var(--cinnabar)}
.consent label{
  margin:0;text-transform:none;letter-spacing:.01em;
  font-family:'Inter Tight',system-ui,sans-serif;font-size:.88rem;
  color:var(--type-dim);line-height:1.5;
}

/* ---------- findings (SCREEN 4) ---------- */
/* position:relative + a stacking context for the absolutely-placed corner
   and background glyphs, so decoration never sits above the text. */
.finding{border-top:1px solid var(--rule);padding:2.2rem 0 0;margin-bottom:2.6rem;position:relative}
.finding > *{position:relative;z-index:1}
.finding .num{
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.62rem;letter-spacing:.26em;text-transform:uppercase;
  color:var(--type-dim);margin-bottom:1rem;display:block;
}
.finding .num b{color:var(--cinnabar-lift);font-weight:500}
/* the FINDING sits close to the section label in visual weight */
.finding h2{
  font-size:clamp(1.5rem,5.9vw,2rem);
  margin-bottom:1.1rem;
}
/* one hand-drawn illustration per finding, at most, placed differently each
   time: a faint corner mark, an inline companion to the heading, or a very
   faint background glyph. Never inside a circle/rounded-square container,
   never filled icon-font glyphs. */
/* ONE treatment for every finding figure -- same size, same weight, same
   place. They previously had three different placements and opacities (a
   44px corner mark, an inline mark left of the heading, and a 210px glyph at
   7% opacity), which read as three unrelated decisions instead of a system.

   Below 1180px the column and the prose are the same width, so there is no
   margin to sit in: the figure becomes a small corner mark and the heading
   is padded to keep clear of it. */
.fig-margin{
  position:absolute;top:0;right:0;width:42px;
  color:var(--type-dim);opacity:.7;z-index:0;pointer-events:none;
}
.finding > h2{padding-right:56px}

details.deeper{margin-top:1.2rem}
details.deeper summary{
  list-style:none;cursor:pointer;display:inline-flex;align-items:center;gap:.6rem;
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.64rem;letter-spacing:.22em;text-transform:uppercase;
  color:var(--cinnabar-lift);
  padding:.7rem 0;min-height:44px;
}
details.deeper summary::-webkit-details-marker{display:none}
details.deeper summary::after{content:"+";font-size:1rem;line-height:1}
details.deeper[open] summary::after{content:"–"}
details.deeper[open] summary{color:var(--type-dim)}
details.deeper .inner{padding-top:.4rem}

/* ---------- the match question ---------- */
.match{
  border-top:1px solid var(--rule);
  padding-top:2rem;margin-bottom:3rem;
}
.match .q{
  font-family:Spectral,Georgia,serif;font-weight:300;
  font-size:1.15rem;margin-bottom:1.1rem;
}
.match .options{display:grid;gap:.6rem}
@media (min-width:560px){.match .options{grid-template-columns:repeat(3,1fr)}}
.match button{
  background:transparent;border:1px solid var(--rule);border-radius:2px;
  color:var(--type);font-family:'Inter Tight',system-ui,sans-serif;
  font-size:.92rem;padding:.85rem 1rem;cursor:pointer;min-height:48px;
  transition:border-color .18s ease,background .18s ease;
}
.match button:hover{border-color:var(--cinnabar-lift)}
.match button[aria-pressed="true"]{
  border-color:var(--cinnabar);background:rgba(178,58,46,.14);
}
.match .thanks{color:var(--type-dim);font-size:.88rem;margin-top:.9rem}

/* ---------- life areas (component only — see build notes; not wired
   into any template by default: see the reply that shipped this file) ---------- */
.life-areas{margin-top:1rem}
.life-grid{display:grid;grid-template-columns:1fr 1fr;gap:0}
@media (min-width:600px){.life-grid{grid-template-columns:1fr 1fr 1fr}}
.life-item{
  padding:1.7rem 1rem 1.9rem;border-top:1px solid var(--rule);
  text-align:center;display:flex;flex-direction:column;align-items:center;gap:.7rem;
}
.life-item svg{width:46px;height:46px;color:var(--type)}
.life-item .li-label{
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.68rem;letter-spacing:.2em;text-transform:uppercase;color:var(--type);
}
.life-item .li-rule{width:1rem;height:1px;background:var(--rule)}
.life-item .li-text{font-size:.85rem;line-height:1.55;color:var(--type-dim);max-width:15rem}

/* ---------- SCREEN 5 — the turn ---------- */
.turn{
  min-height:88vh;
  display:flex;flex-direction:column;justify-content:center;
  text-align:center;padding:7rem 0 6rem;
}
.turn .year{
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:clamp(2.6rem,13vw,4rem);font-weight:400;
  letter-spacing:.06em;line-height:1;color:var(--type);
}
.turn .word{
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.72rem;letter-spacing:.44em;text-transform:uppercase;
  color:var(--cinnabar-lift);margin-top:.9rem;
}
.turn .say{
  font-family:Spectral,Georgia,serif;font-weight:300;
  font-size:clamp(1.15rem,4.8vw,1.45rem);line-height:1.5;
  color:var(--type-dim);margin-top:1.2rem;max-width:30rem;
  margin-left:auto;margin-right:auto;
}
/* a wavy hand-drawn thread instead of a plain gradient rule */
.turn-thread{
  position:relative;width:1px;height:5.5rem;margin:3.4rem auto;
  background:linear-gradient(var(--rule),var(--cinnabar),var(--rule));
}
.turn-thread svg{
  position:absolute;left:50%;top:0;transform:translateX(-50%);
  width:22px;height:100%;color:var(--type-dim);opacity:.55;
}
.turn .block-2027 .year{color:var(--type)}

/* ---------- the offer ---------- */
.offer{
  border-top:1px solid var(--rule);
  padding-top:2.4rem;text-align:center;
}
.offer .of-mark{width:28px;height:28px;margin:0 auto .7rem;color:var(--type-dim);opacity:.85}

/* the two-page report preview — decorative chrome only, no per-reader claim */
.report-preview{position:relative;width:100%;max-width:15rem;height:14.6rem;margin:0 auto 1.8rem}
.report-preview .page{
  position:absolute;background:var(--paper);color:#1A2029;border-radius:1px;
  box-shadow:0 20px 44px -16px rgba(0,0,0,.6);padding:1.1rem 1rem;text-align:left;
}
.report-preview .page.back{width:83%;height:88%;top:1.4rem;right:0;transform:rotate(3.5deg);z-index:1}
.report-preview .page.front{width:83%;height:88%;top:0;left:0;transform:rotate(-3deg);z-index:2}
.report-preview .p-mono{
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.5rem;letter-spacing:.16em;text-transform:uppercase;color:#8A7F6E;
}
.report-preview .p-row{display:flex;justify-content:space-between;align-items:center;margin-bottom:.6rem}
.report-preview .front .p-title{
  font-family:Spectral,Georgia,serif;font-weight:300;
  font-size:1.05rem;line-height:1.25;color:#1A2029;margin:1.7rem 0 .5rem;text-align:center;
}
.report-preview .front .p-rule{width:70%;height:1px;background:rgba(26,32,41,.22);margin:.4rem auto .5rem}
.report-preview .front .p-sub{
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.44rem;letter-spacing:.14em;text-transform:uppercase;color:#8A7F6E;text-align:center;
}
.report-preview .front .p-foot{
  position:absolute;bottom:.8rem;left:1rem;right:1rem;display:flex;justify-content:space-between;
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.42rem;letter-spacing:.12em;text-transform:uppercase;color:#8A7F6E;
}
.report-preview .back .p-heading{
  font-family:Spectral,Georgia,serif;font-weight:300;font-size:.8rem;color:#1A2029;margin:.9rem 0 .5rem;
}
.report-preview .back .p-line{height:1px;background:rgba(26,32,41,.14);margin:.35rem 0}
@media (min-width:600px){.report-preview{max-width:19rem;height:18rem}}

.offer .kicker{
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.62rem;letter-spacing:.26em;text-transform:uppercase;
  color:var(--type-dim);
}
.offer h2{margin:.9rem 0 .8rem}
.offer p{color:var(--type-dim);font-size:.94rem;max-width:28rem;margin:0 auto 1rem}
.offer .capacity{
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.62rem;letter-spacing:.2em;text-transform:uppercase;
  color:var(--cinnabar-lift);margin-bottom:1.7rem;
}
.offer .under-button{
  color:var(--type-dim);font-size:.84rem;line-height:1.6;
  max-width:26rem;margin:1.1rem auto 0;
}
.reserved-note{
  color:var(--type);font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.66rem;letter-spacing:.2em;text-transform:uppercase;
  margin-top:1.2rem;
}

/* ---------- footer ---------- */
footer.site{
  border-top:1px solid var(--rule);
  margin-top:3.2rem;padding-top:1.8rem;text-align:center;
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.62rem;letter-spacing:.09em;color:var(--dim-warm);line-height:1.9;
}

/* ---------- the hand-drawn line-draw reveal ----------
   Pure CSS: the icon's own stroke animates in on load. No JS required, and
   prefers-reduced-motion shows the finished line instantly. */
@keyframes mpDraw{100%{stroke-dashoffset:0}}
.mp-draw path{
  stroke-dasharray:320;stroke-dashoffset:320;
  animation:mpDraw 1.7s ease-out .1s 1 forwards;
}
@media (prefers-reduced-motion:reduce){
  .mp-draw path{animation:none;stroke-dashoffset:0}
}

/* ==========================================================================
   THE OPENING SEQUENCE — ten beats, nothing else moves

   The sequence is CUMULATIVE: the script adds .at-1 … .at-N as each beat
   fires, so every rule below is a single selector rather than an N-squared
   cascade. `data-beat` is kept as the readable state for tests and for the
   ?beat= screenshot pin.
   ========================================================================== */
.beat{opacity:0;transition:opacity .5s ease}
.at-1 .beat-1,.at-2 .beat-2,.at-3 .beat-3,.at-4 .beat-4,.at-5 .beat-5,
.at-6 .beat-6,.at-7 .beat-7,.at-8 .beat-8,.at-9 .beat-9,.at-10 .beat-10{opacity:1}

/* beat 2: the eight characters, neutral. beat 3: the day master turns
   cinnabar, and it is the only thing on the card that does. */
.seq .card td.dm{color:#1A2029;transition:color .55s ease}
.seq .card td.dm::after{opacity:0;transition:opacity .55s ease}
.at-3 .card td.dm{color:var(--cinnabar)}
.at-3 .card td.dm::after{opacity:.55}

/* beat 5: a hairline extends downward into the page */
.seq .thread span{height:0;transition:height .75s ease}
.at-5 .thread span{height:100%}

.beat-4{
  text-align:center;
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.64rem;letter-spacing:.3em;text-transform:uppercase;
  color:var(--cinnabar-lift);padding-top:1rem;
}
.beat-6{
  text-align:center;
  font-family:Spectral,Georgia,serif;font-weight:300;font-style:italic;
  font-size:clamp(1.05rem,4.4vw,1.25rem);line-height:1.5;
  color:var(--type-dim);max-width:28rem;margin:0 auto;padding:.6rem 0 2.4rem;
}

/* --------------------------------------------------------------------------
   BEATS 8–10 — the chart becomes an evidence diagram
   8  the 2026 pillar enters, set apart
   9  a line joins 丙 to the reader's day master stem
   10 a line joins 午 to the ONE branch the contact rule selected, and marks it
   -------------------------------------------------------------------------- */
.card.diagram{padding-top:1.9rem;padding-bottom:2.1rem;position:relative}
.card.diagram .chartrow{padding:.7rem 0 1rem}
.chartrow{display:flex;align-items:stretch;gap:.9rem;position:relative;z-index:2}
.chartrow table{flex:1 1 auto}

.year2026{
  flex:0 0 auto;display:flex;flex-direction:column;align-items:center;
  padding-left:.9rem;
  border-left:1px solid rgba(26,32,41,.22);
}
.year2026 .y-cap{
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.58rem;letter-spacing:.2em;color:#847A6B;
  padding-bottom:.55rem;
}
/* Deliberately NOT cinnabar. Cinnabar is the reader's own character alone. */
.year2026 .y-cell{
  font-family:Spectral,Georgia,serif;font-weight:300;color:#1A2029;
  font-size:clamp(1.75rem,9.4vw,2.4rem);line-height:1.25;
  padding:.15rem 0 .45rem;
}

/* The marked branch. A ring in ink, never the day master's red: two meanings,
   two treatments. */
.card td.contact{position:relative}
.card td.contact::before{
  content:"";position:absolute;left:50%;top:50%;
  width:2.15rem;height:2.35rem;transform:translate(-50%,-54%);
  border:1px solid rgba(26,32,41,.5);border-radius:3px;
  opacity:0;transition:opacity .5s ease;
}
.at-10 .card td.contact::before{opacity:1}

/* The connectors. Drawn by script, revealed by beat. */
.card .links{
  position:absolute;inset:0;width:100%;height:100%;
  pointer-events:none;overflow:visible;z-index:1;
}
.card .links path{
  fill:none;stroke:rgba(26,32,41,.55);stroke-width:1.25;
  stroke-linecap:round;
  stroke-dasharray:var(--len,0);stroke-dashoffset:var(--len,0);
  transition:stroke-dashoffset .7s ease;
}
.at-9 .links .link-stem{stroke-dashoffset:0}
.at-10 .links .link-branch{stroke-dashoffset:0}
/* NONE: the 午 line is drawn short and stops, unconnected. Absence of contact
   is the finding, so the 2026 pillar is never hidden. */
.card .links path.link-open{stroke-dasharray:2 3;stroke-dashoffset:0;opacity:0;
  transition:opacity .5s ease}
.at-10 .links .link-open{opacity:.75}

/* RESPECT prefers-reduced-motion: the same END STATE, instantly. */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;
  }
  .beat{opacity:1!important}
  .seq .card td.dm{color:var(--cinnabar)!important}
  .seq .card td.dm::after{opacity:.55!important}
  .seq .thread span{height:100%!important}
  .card td.contact::before{opacity:1!important}
  .card .links path{stroke-dashoffset:0!important}
  .card .links path.link-open{opacity:.75!important}
  /*  No strike and no flare: a reader who asked for less motion gets the lit
      mark, sitting still. */
  .tiny-mark{animation:none!important;transform:none!important}
  .soul::after{display:none!important}
}

/* ==========================================================================
   WIDTHS. Phone first, but the desktop view is not a stretched phone.
   ========================================================================== */
@media (min-width:720px){                 /* tablet — 820px lands here */
  body{font-size:18px;padding:0 2rem 6rem}
  .card{padding:2.1rem 2rem 2.3rem}
  .hinge{padding:2.2rem 2rem}
  section{padding-bottom:3.4rem}
  .masthead{padding:3.6rem 0 2.2rem}
}
@media (min-width:1024px){                /* desktop — 1440px lands here */
  body{padding:0 2rem 7rem}
  /* The measure stays put and the ground fills the rest of the monitor. */
  .masthead{padding:4.6rem 0 2.4rem}
  .turn{min-height:92vh;padding:9rem 0 7rem}
  .finding{padding-top:2.6rem}
}

/* ---------- /leads ---------- */
.admin{max-width:none}
.admin table{width:100%;border-collapse:collapse;font-size:.78rem}
.admin th,.admin td{
  border-bottom:1px solid var(--rule);padding:.5rem .6rem;text-align:left;
  font-family:'IBM Plex Mono',ui-monospace,monospace;white-space:nowrap;
}
.admin th{color:var(--type-dim);font-size:.6rem;letter-spacing:.16em;text-transform:uppercase}
.admin .scroll{overflow-x:auto;-webkit-overflow-scrolling:touch}
.admin .warn{
  border-left:2px solid var(--cinnabar);background:var(--ink-2);
  padding:1rem 1.2rem;margin-bottom:1.6rem;font-size:.86rem;
}

/* ---------- placeholder-content banner (development only) ---------- */
/* Only rendered when a non-Daniel block is served, which requires strict canon
   to be OFF. It cannot appear in production. */
.draft-banner{
  border-left:2px solid var(--cinnabar);
  background:rgba(178,58,46,.12);
  padding:.95rem 1.1rem;margin-bottom:1.2rem;
  font-size:.84rem;line-height:1.55;color:var(--type-dim);
}
.draft-banner b{color:var(--cinnabar-lift);font-weight:500;display:block}
.draft-banner code{font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:.92em}

/* ---------- the contact layer: a STEP inside the 2026 argument ----------
   Deliberately lighter than a section heading. It is not a fifth section, it
   is the second half of one finding. */
.contact-step{margin-top:1.7rem}
.contact-step .step-rule{
  height:1px;background:var(--rule);margin-bottom:1.1rem;
}
.contact-step .step-label{
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.6rem;letter-spacing:.26em;text-transform:uppercase;
  color:var(--type-dim);margin-bottom:.9rem;
}
.contact-step .step-position{
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.72rem;letter-spacing:.16em;color:var(--type);
  margin-bottom:.35rem;
}
.contact-step .step-relation{
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.62rem;letter-spacing:.22em;text-transform:uppercase;
  color:var(--cinnabar-lift);margin-bottom:.9rem;
}
.contact-step h3.step-headline{
  font-family:Spectral,Georgia,serif;font-weight:300;
  font-size:clamp(1.15rem,4.6vw,1.4rem);line-height:1.3;letter-spacing:-.005em;
  color:var(--type);text-transform:none;margin:0 0 .9rem;
}
.contact-step .consequence{
  font-family:Spectral,Georgia,serif;font-weight:300;
  font-size:clamp(1.1rem,4.4vw,1.3rem);line-height:1.45;color:var(--type);
}
.checkline{
  margin-top:1.5rem;padding-top:1.1rem;border-top:1px solid var(--rule);
  font-family:Spectral,Georgia,serif;font-style:italic;font-weight:300;
  font-size:1.02rem;line-height:1.55;color:var(--type-dim);
}

/* ================= THE REST OF YOUR 2026 — the rhythm layer =================
   The bridge between proof and foresight. Restrained, monochrome, and
   deliberately not a chart: no bars, no numbers, no colour coding of good and
   bad. The line rises and falls because rise and fall is the finding. */
.rhythm{padding-top:.6rem;margin-bottom:3rem}
.rhythm .step-rule{height:1px;background:var(--rule);margin-bottom:1.15rem}
.rhythm-closed{
  font-family:Spectral,Georgia,serif;font-weight:300;font-style:italic;
  font-size:1.05rem;color:var(--type-dim);margin-bottom:1rem;
}

.strip{margin:.4rem 0 2.4rem}
.strip-plot{position:relative;height:5.5rem}
.strip svg{display:block;width:100%;height:100%;overflow:visible}
/* Every dot the same size, always circular. */
.strip .dot{
  position:absolute;width:7px;height:7px;margin:-3.5px 0 0 -3.5px;
  border-radius:50%;background:var(--type);
}
/* one ink tone throughout, one dot size. Nothing here encodes good or bad. */
.strip svg polyline{
  fill:none;stroke:var(--type-dim);stroke-width:.5;
  stroke-linejoin:round;stroke-linecap:round;vector-effect:non-scaling-stroke;
}
.strip-labels{display:flex;margin-top:.75rem}
.strip-col{
  flex:1 1 0;min-width:0;display:flex;flex-direction:column;
  align-items:center;text-align:center;gap:.3rem;
}
.strip-col .m{
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.6rem;letter-spacing:.18em;color:var(--type-dim);
}
.strip-col .l{
  font-family:'IBM Plex Mono',ui-monospace,monospace;font-weight:500;
  font-size:.5rem;letter-spacing:.02em;color:var(--type);
  text-transform:uppercase;line-height:1.25;overflow-wrap:anywhere;hyphens:auto;
}
@media (min-width:600px){
  .strip-col .l{font-size:.55rem;letter-spacing:.08em}
}

.months{display:grid;gap:1rem}
@media (min-width:600px){.months{grid-template-columns:1fr 1fr}}
.month-card{
  background:var(--ink-2);backdrop-filter:blur(6px);
  border-left:1px solid var(--rule);
  border-radius:0 2px 2px 0;padding:1.15rem 1.2rem;
}
.month-card .m-icon{width:26px;height:26px;color:var(--type-dim);opacity:.85;margin-bottom:.5rem}
.month-card .m-name{
  font-family:'IBM Plex Mono',ui-monospace,monospace;font-weight:500;
  font-size:.78rem;letter-spacing:.24em;text-transform:uppercase;color:var(--type);
}
.month-card .m-begins{
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.6rem;letter-spacing:.12em;color:var(--type-dim);margin-top:.3rem;
}
.month-card .m-state{
  font-family:'IBM Plex Mono',ui-monospace,monospace;font-weight:500;
  font-size:.66rem;letter-spacing:.2em;text-transform:uppercase;
  color:var(--cinnabar-lift);margin:.9rem 0 .5rem;
}
.month-card .m-line{
  font-family:Spectral,Georgia,serif;font-weight:300;
  font-size:1.02rem;line-height:1.4;color:var(--type);margin-bottom:.6rem;
}
.month-card .m-body{font-size:.88rem;line-height:1.6;color:var(--type-dim);margin:0}

@media (min-width:1024px){
  .strip-plot{height:6.5rem}
}



/* ---------------------------------------------------------------------------
   THE 2027 OFFER AND ENQUIRY
   Deliberately plain: this is a commercial form, not another set piece. It
   inherits the page's ink, measure and field styling so it cannot drift into
   looking like a different site.
--------------------------------------------------------------------------- */
.offer .price{margin:.7rem 0 1.1rem}
.offer .price .amount{
  font-family:'Spectral',Georgia,serif;font-size:clamp(2.2rem,7vw,3rem);
  font-weight:300;color:var(--type);letter-spacing:.01em;line-height:1}
.offer .inclusions{
  list-style:none;padding:0;margin:0 0 1.2rem;max-width:var(--measure);
  text-align:left}
.offer .inclusions li{
  position:relative;padding:.42rem 0 .42rem 1.5rem;
  border-bottom:1px solid rgba(187,161,135,.14);font-size:.97rem}
.offer .inclusions li:last-child{border-bottom:0}
.offer .inclusions li::before{
  content:"";position:absolute;left:.25rem;top:1.02em;
  width:.42rem;height:.42rem;border-radius:50%;background:var(--cinnabar);opacity:.85}
.offer .review-line{
  max-width:var(--measure);font-style:italic;color:var(--type);margin:.2rem 0 .9rem}

form.enquiry{
  display:grid;gap:1rem;max-width:var(--measure);
  margin:1.6rem auto 0;padding-top:1.4rem;
  border-top:1px solid rgba(187,161,135,.2);text-align:left}
form.enquiry .eyebrow{margin-bottom:.2rem}
/* The details already given during the 2026 demo. Shown for confirmation
   only -- read-only by construction, because they are not inputs at all. */
form.enquiry .known{
  background:rgba(20,13,9,.42);border:1px solid rgba(187,161,135,.16);
  border-radius:3px;padding:.9rem 1rem}
form.enquiry .known-row{
  display:flex;justify-content:space-between;gap:1rem;
  padding:.34rem 0;border-bottom:1px solid rgba(187,161,135,.1);
  font-size:.93rem}
form.enquiry .known-row:last-of-type{border-bottom:0}
form.enquiry .known-row span{color:var(--type-dim);white-space:nowrap}
form.enquiry .known-row b{font-weight:400;text-align:right}
form.enquiry .known .fineprint{margin:.6rem 0 0;text-align:left}
.enquiry-done{
  max-width:var(--measure);margin:1.6rem auto 0;padding:1.2rem 1.1rem;
  border:1px solid rgba(187,161,135,.28);border-radius:3px;
  background:rgba(20,13,9,.5);text-align:left}
.enquiry-done h3{
  font-family:'Spectral',Georgia,serif;font-weight:300;
  font-size:1.35rem;margin:0 0 .5rem;color:var(--type)}
.enquiry-done p{margin:0;color:var(--type-dim)}

@media (max-width:420px){
  /* stacked, so a long place name never squashes its own label */
  form.enquiry .known-row{flex-direction:column;gap:.1rem}
  form.enquiry .known-row b{text-align:left}
}

/* /leads only: a paying-intent lead must not look like a demo completion. */
.yes-2027{color:var(--cinnabar);letter-spacing:.06em}
.notify-warn{color:#C9873F}

/*  EARLY-BIRD PRICING.
    The number leads; the tag is a quiet letterpress mark beside it, not a
    sale badge. No strike-through, no red "was" price, no countdown -- the
    deadline is real and stated in words. */
.offer .price{display:flex;align-items:baseline;gap:.65rem;flex-wrap:wrap}
.offer .price .tag{
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.66rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--cinnabar);border:1px solid rgba(178,58,46,.5);
  border-radius:2px;padding:.24rem .5rem;white-space:nowrap}
.offer .price-note{
  max-width:var(--measure);margin:-.5rem 0 1.1rem;
  font-size:.9rem;color:var(--type-dim);line-height:1.55}
.offer-tag{color:var(--type);letter-spacing:.05em}

/* ---------------------------------------------------------------------------
   YOUR 2027 PRIORITIES
   Editorial, not a personality quiz: no icons, no colour-coded tiles, no
   progress bar. Selection reads as ink and a rule, the way the rest of the
   page does. The rank badge is what teaches primary vs secondary.
--------------------------------------------------------------------------- */
/*  `.offer` centres its own text, and the focus block sits inside it. Left
    alignment is set once here so the headings line up with the cards instead
    of floating over them. */
.focus{
  display:grid;gap:.9rem;padding-top:1.3rem;margin-top:.4rem;
  border-top:1px solid rgba(187,161,135,.2);text-align:left}
.focus-lead{margin:0;color:var(--type-dim);font-size:.95rem}
/*  The single implicit column was being sized to its widest item and then
    placed centrally, so the short headings sat at x=139 inside a parent whose
    content box starts at x=22. `justify-self` did not help -- the ITEM was
    already at the start of a narrow TRACK. Pinning the track to the full width
    is the actual fix. */
.focus-block{
  display:grid;gap:.55rem;
  grid-template-columns:minmax(0,1fr);justify-content:stretch}
/*  These blocks are GRID containers, and the short headings were landing as
    shrink-to-fit items placed centrally in their column -- a 111px box inside
    347px -- so "MAIN FOCUS" floated away from the cards it labels while the
    long paragraphs beside it looked correctly aligned. It reads as a
    text-align problem and is not one: `text-align` already computed to left.
    `justify-self:start` is the fix, at the grid level where the offset is. */
/*  These headings were rendering CENTRED inside their grid track: measured
    offsets were exactly (track - width) / 2, so the short labels floated away
    from the cards they name while the long paragraphs looked fine.
    `justify-self:start` did not win the cascade here, so the box is made to
    fill the track outright -- with text-align already left, the text then
    starts where the cards start. Verified by measurement, not by eye. */
/*  Scoped under `.focus` for SPECIFICITY, not for tidiness. `.offer p` sets
    `max-width:28rem; margin:0 auto` and is (0,1,1); a bare `.focus-lead` is
    (0,1,0) and loses, so these paragraphs were capped at 448px and centred
    inside a 640px column -- landing exactly 96px right of the cards they
    label. Adding the ancestor makes them (0,2,0) and they win. */
.focus .focus-step,.focus .focus-hint,.focus .focus-lead,
.focus .focus-block,.focus .focus-open,.focus .focus-context{
  width:100%;justify-self:stretch;
  margin-left:0;margin-right:0;max-width:none}
.focus-step{
  margin:0 0 0;font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.7rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--cinnabar)}
/*  The supporting block is quieter than the main block, so the hierarchy is
    legible before anything is read. */
#supporting-block .focus-step{color:var(--type-dim)}
.focus-hint{margin:0;font-size:.88rem;color:var(--type-dim)}
.focus-grid{display:grid;gap:.6rem}
@media (min-width:600px){.focus-grid{grid-template-columns:1fr 1fr}}

/*  A focus card IS a <label>, so it inherits the form's label rule --
    0.6rem uppercase monospace with 0.24em tracking. That turned six editorial
    sentences into shouted terminal text. The card resets its own typography
    rather than the global label rule being weakened for every other field. */
.focus-card{
  position:relative;display:block;cursor:pointer;
  font-family:'Inter Tight',system-ui,-apple-system,sans-serif;
  font-size:1rem;letter-spacing:normal;text-transform:none;
  color:var(--type);margin-bottom:0;
  padding:.85rem 1rem .9rem;border:1px solid rgba(187,161,135,.22);
  border-radius:3px;background:rgba(20,13,9,.34);
  transition:border-color .18s ease,background .18s ease}
.focus-card:hover{border-color:rgba(187,161,135,.42)}
/* the checkbox stays in the accessibility tree and keyboard order; it is the
   card that shows state. Never display:none -- that removes it from both. */
.focus-card input{position:absolute;opacity:0;width:1px;height:1px}
.focus-card input:focus-visible ~ .focus-name{outline:2px solid var(--cinnabar);
  outline-offset:3px}
.focus-name{
  display:block;font-family:'Spectral',Georgia,serif;font-weight:400;
  font-size:1.06rem;line-height:1.3;letter-spacing:normal;text-transform:none;
  color:var(--type);margin-bottom:.25rem}
.focus-desc{
  display:block;font-family:'Inter Tight',system-ui,-apple-system,sans-serif;
  font-size:.85rem;letter-spacing:normal;text-transform:none;
  color:var(--type-dim);line-height:1.5}
.focus-rank{
  display:none;font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.6rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--cinnabar);margin-bottom:.3rem}
.focus-card.is-on{border-color:rgba(178,58,46,.55);background:rgba(46,20,14,.42)}
.focus-card.is-on .focus-rank{display:block}
.focus-card.is-secondary{border-color:rgba(187,161,135,.5)}
.focus-card.is-secondary .focus-rank{color:var(--type-dim)}
.focus-card input:disabled ~ .focus-name,
.focus-card input:disabled ~ .focus-desc{opacity:.4}

.focus-context{display:grid;gap:.35rem}
.focus-open{display:grid;gap:.35rem}
.focus-open .opt{
  font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:.62rem;
  letter-spacing:.12em;text-transform:uppercase;color:var(--type-dim)}
.focus-open textarea{
  width:100%;font:inherit;font-size:.97rem;color:var(--type);
  background:rgba(20,13,9,.42);border:1px solid rgba(187,161,135,.22);
  border-radius:3px;padding:.7rem .8rem;resize:vertical;min-height:5.2rem}
.focus-open textarea:focus{outline:none;border-color:rgba(178,58,46,.55)}
.focus-open .fineprint{margin:0;text-align:left}

/* /leads focus tables */
.focus-demand td:first-child{white-space:nowrap}

/*  International phone entry. Country first and full width: it is the part
    people forget, and a half-width control next to a half-width number box
    makes both too small to read on a phone. */
form.enquiry .phone-field{display:grid;gap:.45rem}
form.enquiry .phone-country{width:100%}
form.enquiry .phone-field .fineprint{margin:.1rem 0 0;text-align:left}

/* ---------------------------------------------------------------------------
   THE TWELVE 2026 MONTHS
   Vertical on a phone: twelve cards behind a horizontal swipe are twelve
   cards nobody reads. Past / now / coming up is carried by one small label
   and a change in weight -- never by colour coding, which would read as
   good and bad.
--------------------------------------------------------------------------- */
/*  Scoped to the EXISTING `.months` class rather than adding a second one:
    a layout test slices the page between `class="strip"` and `class="months"`,
    and `class="months year-months"` no longer contains that exact string, so
    the slice ran to the end of the document and swept in the card prose. */
.rhythm .months .month-card{position:relative}
.m-tense{
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.6rem;letter-spacing:.18em;text-transform:uppercase;
  color:var(--type-dim);margin-bottom:.5rem}
/*  A month already lived is quieter -- it is evidence, and the reader
    already knows how it went. */
.month-card.is-past{opacity:.72}
.month-card.is-past .m-tense{color:var(--type-dim)}
/*  The month being lived right now is the one to find at a glance. */
.month-card.is-current{
  border-color:rgba(178,58,46,.5);background:rgba(46,20,14,.34)}
.month-card.is-current .m-tense{color:var(--cinnabar)}
.month-card.is-upcoming .m-tense{color:var(--type-dim)}
/*  Cards run 50-90 words by design. Equal height would mean padding short
    ones with filler, so they are allowed to differ and the grid aligns
    their tops instead. */
.rhythm .months{align-items:start}

/* ---------------------------------------------------------------------------
   YOUR 2026 RHYTHM — the twelve-month overview
   The chart is a shape, never a score. No percentages, no ratings, no red and
   green. Past / now / coming up is carried by weight and one cinnabar mark.
--------------------------------------------------------------------------- */
.rhythm-explain{
  max-width:var(--measure);margin:.2rem 0 .5rem;
  color:var(--type-dim);font-size:.95rem;line-height:1.6}
.rhythm-explain-sub{
  max-width:var(--measure);margin:0 0 1.4rem;
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.74rem;letter-spacing:.06em;color:var(--type-dim);line-height:1.6}

/*  Twelve columns rather than six. */
.strip-labels{grid-template-columns:repeat(12,1fr)}
.strip-col.is-past{opacity:.55}
.strip-col.is-current .m{color:var(--cinnabar)}
.strip-col.is-current .l{color:var(--type)}
.dot.is-past{opacity:.5}
/*  The one month being lived. A ring, not a bigger dot -- size would read as
    magnitude, and this is a position in time, not a quantity. */
.dot.is-current{
  background:var(--cinnabar);
  box-shadow:0 0 0 3px rgba(178,58,46,.28)}

/*  MOBILE: twelve rhythm words under a 347px chart collide into an
    unreadable band. The month and the plotted point are what the overview is
    for; the card below already carries the rhythm word, the line and the
    explanation. Readability wins over completeness, and nothing is lost. */
@media (max-width:600px){
  .strip-labels .l{display:none}
  .strip-labels .m{font-size:.56rem;letter-spacing:.02em}
}

/* ---------------------------------------------------------------------------
   THE PRACTITIONER PORTAL — admin only, never reachable by a customer.
   Plain and dense on purpose: this is a working screen, not a set piece.
--------------------------------------------------------------------------- */
.prepare-link{color:var(--cinnabar);white-space:nowrap}
.portal-status{display:flex;gap:2rem;flex-wrap:wrap;margin:.6rem 0 1.2rem}
.portal-status div{display:grid;gap:.15rem}
.portal-status span{
  font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:.6rem;
  letter-spacing:.16em;text-transform:uppercase;color:var(--type-dim)}
.portal-error,.portal-notice,.portal-block{
  max-width:var(--shell);margin:0 0 1rem;padding:.8rem 1rem;border-radius:3px;
  border:1px solid rgba(187,161,135,.28);background:rgba(20,13,9,.5)}
.portal-error{border-color:rgba(178,58,46,.6);color:var(--type)}
.portal-block ul{margin:.4rem 0 0 1.1rem;color:var(--type-dim)}
.portal-grid{display:grid;gap:1rem;margin-bottom:1rem}
@media (min-width:820px){.portal-grid{grid-template-columns:1fr 1fr}}
.portal-card{
  border:1px solid rgba(187,161,135,.2);border-radius:3px;
  background:rgba(20,13,9,.42);padding:1rem 1.1rem;margin-bottom:1rem;
  text-align:left}
.portal-card h3{
  font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:.68rem;
  letter-spacing:.16em;text-transform:uppercase;color:var(--cinnabar);
  margin:0 0 .7rem;font-weight:500}
.portal-card dl{display:grid;grid-template-columns:auto 1fr;gap:.3rem .9rem;margin:0}
.portal-card dt{color:var(--type-dim);font-size:.85rem;white-space:nowrap}
.portal-card dd{margin:0;font-size:.95rem}
.portal-card .cjk{font-size:1.15rem}
.portal-question{margin:.8rem 0 0;font-size:.95rem}
.portal-question span{
  display:block;font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.6rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--type-dim);margin-bottom:.2rem}
.portal-brief{margin:0 0 1rem}
.portal-brief pre{
  white-space:pre-wrap;font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.72rem;line-height:1.6;color:var(--type-dim);
  background:rgba(20,13,9,.5);padding:.9rem;border-radius:3px;overflow-x:auto}
.portal-move{
  border-top:1px solid rgba(187,161,135,.16);padding-top:.8rem;margin-top:.8rem}
.portal-move .move-label{
  font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:.6rem;
  letter-spacing:.16em;text-transform:uppercase;color:var(--cinnabar);
  margin-bottom:.3rem}
.portal-move input,.portal-move textarea{width:100%}
.portal-actions{display:flex;gap:.6rem;flex-wrap:wrap;align-items:center}
.portal-actions form{margin:0}
.btn.ghost{background:transparent;color:var(--type);
  border:1px solid rgba(187,161,135,.4)}
.btn[disabled]{opacity:.4;cursor:not-allowed}

/* ---- internal plotter -------------------------------------------------- */
.portal-pillars{width:100%;border-collapse:collapse;margin:1rem 0}
.portal-pillars th{font-size:.62rem;letter-spacing:.22em;text-transform:uppercase;
  color:var(--type-dim);font-weight:400;padding-bottom:.5rem}
.portal-pillars td{text-align:center;padding:.15rem 0}
.pillar-stem{font-size:1.9rem;line-height:1.1}
.pillar-branch{font-size:1.9rem;line-height:1.1;color:var(--type-dim)}
.portal-stage-list{list-style:none;padding:0;margin:.5rem 0 0}
.portal-stage-list li{padding:.3rem 0;display:flex;gap:.6rem;align-items:baseline}
.stage-mark{width:1.2em;flex:none}
.stage-ok .stage-mark{color:#4a7c59}
.stage-warn .stage-mark{color:#b8860b}
.stage-blocked .stage-mark{color:#a4442c}

/*  THE YEAR SWITCH ("2026 | 2027"). Top right of the result page. Small,
    mono, one underline for the year on show. Plain links. */
.year-switch{
  display:flex;justify-content:flex-end;align-items:center;gap:.55rem;
  padding:.9rem 0 0;font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:.78rem;letter-spacing:.12em;
}
.year-switch a{
  color:var(--type-dim);text-decoration:none;padding:.35rem .15rem;
  border-bottom:1px solid transparent;
}
.year-switch a:hover{color:var(--type)}
.year-switch a.on{color:var(--type);border-bottom-color:var(--cinnabar-lift)}
.year-switch a:focus-visible{outline:2px solid var(--type-dim);outline-offset:3px}
.year-switch .sep{color:var(--rule)}
