/*
 * Overrides for the design-canvas pages: hero legibility, then the responsive
 * layer. Two concerns, one stylesheet, because the artifact needs both and both
 * work the same way.
 *
 * The artifact carries no media queries and styles everything with inline style
 * attributes, which outrank a stylesheet. So every rule here is !important by
 * necessity, not by laziness, and every selector matches on the inline style
 * itself. The runtime re-serialises those attributes through React, which adds a
 * space after each colon, so paired selectors cover both the authored form
 * (flex:1 1 320px) and the rendered one (flex: 1 1 320px).
 *
 * Scope: layout only. No colour, type scale, spacing or motion is changed here.
 * The desktop composition is the design and it is left exactly as authored.
 */

/* ── The sun's size ───────────────────────────────────────────────────────────
 * ONE source of truth. index.html sizes the disc, its bloom and its rays from
 * this, and the hero script MEASURES the disc rather than recomputing it, so
 * nothing can drift out of agreement.
 *
 * 84vh is the authored value and it is right for a landscape screen: on
 * 1440x900 the sun is 756px, a little over half the width, so it reads as a sun
 * on a horizon with sky either side. On a 390x844 phone the same rule gives a
 * 709px disc on a 390px screen — 182% of the width — so there is no horizon and
 * no sky, just an orange wall with the copy lost on it.
 *
 * Portrait therefore sizes the sun from the WIDTH instead, keeping roughly the
 * same sun-to-screen relationship the composition was designed around.
 */
:root {
  --sunD: 84vh;      /* the sun's diameter */
  /* A LENGTH, never a percentage. A percentage resolves against whichever box
     it is used in, and the boot overlay nests its sun inside a clip whose own
     height is already the horizon — so `82%` meant two different numbers in the
     two frames and the sun jumped 123px when the boot overlay handed over. */
  --horizon: calc(var(--vh) * 0.62);
  --vh: 100vh;       /* replaced with the REAL viewport height by the hero script */
  --navH: 0px;       /* measured height of the fixed bar, published by the same */
}

/* Very short landscape windows would otherwise get a sun taller than the frame. */
@media (max-height: 560px) and (min-aspect-ratio: 1 / 1) {
  :root { --sunD: 68vh; }
}

/* ═══════════════════════════════════════════════════════════════════════════
 * PORTRAIT: a different composition, not the landscape one squeezed
 *
 * The landscape hero puts the horizon at 62% and floods the top of the frame
 * with a sun wider than half the screen, then sets the copy across it. That
 * works at 16:9. In portrait it produced, all from the same cause:
 *
 *   - a sun 182% of the screen width, then (once resized) a sun that sat clear
 *     of the horizon as a FULL CIRCLE with its rays showing underneath, because
 *     the script placed it against window.innerHeight while the ground was
 *     drawn at CSS 62vh, and iOS Safari's URL bar makes those different;
 *   - copy sitting on the brightest part of the disc at 1.2:1;
 *   - a third of the screen below the horizon holding nothing.
 *
 * Portrait therefore gets its own geometry rather than overrides on the other
 * one: the ground drops to 78% so the sun rises out of the BOTTOM of the frame,
 * the sun is sized from the width, and the copy lives in the clear band above
 * it. Nothing overlaps, so nothing needs the ink trick — which matters, because
 * the ink trick relies on background-attachment:fixed and iOS Safari does not
 * honour it.
 * ═══════════════════════════════════════════════════════════════════════════ */
@media (max-aspect-ratio: 1 / 1) {

  :root {
    --sunD: 92vw;
    --horizon: calc(var(--vh) * 0.82);
  }

  /* The copy band. The beats are absolutely positioned to the stage and were
     told to fill down to the horizon, which in portrait means their centred
     contents land on the sun's crown. Ending the band above the crown is what
     keeps every line of type on open sky. */
  [data-band] {
    /* Start BELOW the fixed bar, not at the stage's top edge. The bar overlays
       the stage, so centring from y=0 pushed the headline's first line up
       underneath it and clipped it. --navH is measured and published by the
       hero script. */
    top: var(--navH, 0px) !important;
    height: calc(56% - var(--navH, 0px)) !important;
    bottom: auto !important;
    align-items: center !important;
  }

  /* No type crosses the disc in this composition, so the sun clip has no work to
     do — and it must not run here anyway: it depends on
     background-attachment:fixed, which iOS Safari does not honour, so the ink
     lands in the wrong place and the copy stays white on the bright disc. That
     is what shipped and what looked broken on a real phone.
     Plain white on open sky measures 15:1. */
  [data-lit] h1,
  [data-lit] h2,
  [data-lit] p,
  [data-lit] span,
  [data-lit] i {
    background-image: none !important;
    background-attachment: scroll !important;
    color: rgba(255, 250, 244, 0.96) !important;
    -webkit-text-fill-color: rgba(255, 250, 244, 0.96) !important;
    text-shadow: 0 1px 2px rgba(6, 8, 18, 0.55) !important;
  }

  /* "today" keeps its gold: it sits on open sky here and never meets the sun. */
  [data-lit] em {
    background-image: linear-gradient(96deg, #FFD489, #FF7A5B 58%, #FF6B5B) !important;
    -webkit-background-clip: text !important;
    background-clip: text !important;
    -webkit-text-fill-color: transparent !important;
    color: transparent !important;
  }
}

/* ── Below 900px: every two-up composition becomes one column ─────────────── */
@media (max-width: 900px) {

  /* Grids are authored as 2 to 4 explicit tracks. One track fits a phone. */
  [style*="grid-template-columns"] {
    grid-template-columns: minmax(0, 1fr) !important;
  }

  /* Flex columns with a wide basis: let them take the full row instead of
     compressing to a 150px ribbon of two-word lines. */
  [style*="flex:1 1 320px"], [style*="flex: 1 1 320px"],
  [style*="flex:1 1 380px"], [style*="flex: 1 1 380px"],
  [style*="flex:0 1 460px"], [style*="flex: 0 1 460px"],
  [style*="flex:0 0 168px"], [style*="flex: 0 0 168px"],
  [style*="flex:1 1 0"],     [style*="flex: 1 1 0"] {
    flex: 1 1 100% !important;
    max-width: 100% !important;
  }

  /* The email field keeps its own row, with the button beneath it, so neither
     ends up too narrow to read. */
  [style*="flex:1 1 220px"], [style*="flex: 1 1 220px"] {
    flex: 1 1 100% !important;
  }
}

/* ── The horizontal scroll-jack ───────────────────────────────────────────────
 * "How it works" is three full-viewport panels on a 300vw track, dragged
 * sideways by scroll position. That mechanism has nowhere to go on a phone: the
 * panels compress, and the track's own width leaks a panel edge into the hero.
 * Below 900px the section stops being a scroll-jack and becomes three stacked
 * panels, which is what the content was anyway. The JS keeps writing --jack; the
 * transform override below makes that write inert rather than fighting it.
 */

/* The hero's closing beat sets a right-aligned paragraph beside the lockscreen
   mockup, as an overlay filling the hero. The paragraph is capped at 340px with
   flex:0 1 auto, so on a phone it collapses to a 96px ribbon beside the phone.
   Stack the pair and give the copy the width. */
@media (max-width: 900px) {

  [data-ride] [style*="gap:clamp(24px,5vw,70px)"],
  [data-ride] [style*="gap: clamp(24px, 5vw, 70px)"] {
    flex-direction: column !important;
    gap: 22px !important;
  }

  [data-ride] [style*="max-width:340px"],
  [data-ride] [style*="max-width: 340px"] {
    max-width: 100% !important;
    flex: none !important;
    text-align: center !important;
  }
}

@media (max-width: 900px) {

  [data-jack] {
    height: auto !important;
    margin-top: 72px !important;
  }

  /* Unstick the viewport-height frame and stop it clipping. */
  [data-jack] > div {
    position: static !important;
    height: auto !important;
    overflow: visible !important;
  }

  /* The "How it works — 1 / 3" rail is absolutely positioned over the frame.
     Stacked, the step count means nothing, so keep the label and drop the count. */
  [data-jack] > div > div[style*="position:absolute"],
  [data-jack] > div > div[style*="position: absolute"] {
    position: static !important;
    padding: 0 24px 8px !important;
  }
  [data-jack-step] {
    display: none !important;
  }

  [data-track] {
    width: 100% !important;
    height: auto !important;
    transform: none !important;
    flex-direction: column !important;
  }

  /* Each panel was 100vw of a sideways track. Now it is a section. */
  [data-track] > div {
    width: 100% !important;
    flex: none !important;
    height: auto !important;
    padding: 40px 24px !important;
    box-sizing: border-box !important;
  }

  /* And each panel's own two-up interior stacks with it. stretch, not
     flex-start: the artwork beside each panel's copy is a card with an
     intrinsic width, and flex-start shrinks it to that width, leaving a
     third of the screen empty next to it. */
  [data-track] > div > div {
    flex-direction: column !important;
    align-items: stretch !important;
    gap: 28px !important;
  }
}

/* ── Anchor targets clear the fixed bar ───────────────────────────────────────
 * The nav is position:fixed, so an in-page jump (#how, #receipts, #faq, #notify)
 * lands with the heading underneath it. Applies at every width, because the bar
 * is fixed at every width.
 */
html {
  scroll-padding-top: 88px;
}
@media (max-width: 760px) {
  html { scroll-padding-top: 76px; }
}

/* ── Navigation ───────────────────────────────────────────────────────────────
 * Four items do not fit across a phone; they wrap and collide with the wordmark.
 * Below 760px the section links drop and the bar keeps what it is for: the mark,
 * and the one action. The dropped links all exist in the footer, so nothing
 * becomes unreachable.
 *
 * :has(svg) identifies the brand link, which is an <a> on every page except the
 * home page, where it is a <span> and so is unaffected either way.
 */
@media (max-width: 760px) {

  nav a:not(:last-of-type):not(:has(svg)) {
    display: none !important;
  }

  nav > div {
    padding-left: 20px !important;
    padding-right: 20px !important;
    gap: 10px !important;
  }

  /* The CTA is the widest thing left in the bar; shorten its padding rather
     than let it push the wordmark off the edge. */
  nav a:last-of-type {
    padding: 8px 13px !important;
    font-size: 12px !important;
    white-space: nowrap !important;
  }
}

/* ── Long-form pages ──────────────────────────────────────────────────────────
 * privacy, terms, security and about are a narrow measure beside a wide gutter.
 * On a phone the gutter is the whole cost, so reclaim it.
 */
@media (max-width: 760px) {

  [style*="padding:clamp(34px"], [style*="padding: clamp(34px"],
  [style*="clamp(34px,7vw,104px)"], [style*="clamp(34px, 7vw, 104px)"] {
    padding-left: 22px !important;
    padding-right: 22px !important;
  }

  /* Headline sizes are authored in vw-ish clamps that bottom out too large for
     a 390px screen, so a two-word line is common. Nudge the floor down. */
  h1, [style*="font-size:clamp"], [style*="font-size: clamp"] {
    word-break: normal !important;
    overflow-wrap: break-word !important;
  }
}

/* ── Touch and motion ─────────────────────────────────────────────────────── */
@media (hover: none) {
  /* The artifact expresses hover through a style-hover attribute the runtime
     binds. On touch there is no hover state to leave, so make the tap targets
     reach the 44px Apple minimum instead. */
  nav a:last-of-type {
    min-height: 44px !important;
    display: inline-flex !important;
    align-items: center !important;
  }
  button {
    min-height: 44px !important;
  }
}


/* ═══════════════════════════════════════════════════════════════════════════
 * HERO LEGIBILITY
 *
 * The sunrise scroll paints near-white type directly onto the sun's face. The
 * sun's upper gradient is #FFD489 to #FFC46B, so measured against it:
 *
 *   headline  #F7F5F2 at alpha 1.0 ......... 1.44:1
 *   sub-copy  rgba(247,245,242,.60) ........ 1.24:1
 *   row label rgba(247,245,242,.86) ........ 1.37:1
 *   row sub   rgba(247,245,242,.46) ........ 1.18:1
 *
 * AA wants 4.5:1. White cannot get there on a bright sun at ANY alpha: the sun
 * would have to go to roughly #C2570C, a burnt orange, for white to pass. So
 * dimming the sun is the only thing that would fix it by adjusting colour, and
 * dimming the sun is exactly what this must not do.
 *
 * Nothing here touches the sun. No gradient edit, no opacity change, no scrim.
 *
 * <em> ("today") gets its own two-layer treatment rather than the plain one, so
 * it keeps its gold on the night sky and still goes ink under the sun. Do not
 * fold it into the rule above: that overwrites its gradient and flattens the one
 * accent on the page.
 *
 * It is OPT-IN, via data-lit on the six hero text blocks, and that matters: the
 * lockscreen mockup lives in the same hero and carries its own dark screen, so
 * a blanket rule inked its notification copy into unreadability. Measured, not
 * assumed — it rendered that way before the tags were added.
 *
 * The type moves ACROSS the sun as it rises, so no single colour works: the
 * arithmetic rows straddle the limb, and the caption under the horizon is on
 * black, where ink is invisible. Both were measured, not assumed.
 *
 * The fix colours each glyph by where it actually is. A radial gradient matching
 * the sun's own circle is clipped to the text: deep warm ink inside the disc,
 * near-white outside it. background-attachment:fixed anchors that gradient to
 * the viewport, which is the same coordinate space --sun-center is written in,
 * so it tracks the sun frame by frame with no JS. A word half over the limb is
 * half ink and half white, which is what light falling across type looks like.
 *
 * Measured on the same gradient: ink #3B1A08 gives 10.0:1 on the sun's face,
 * and white gives 15:1+ on the night sky. Both ends pass AAA.
 *
 * Every rule is !important for the same reason the responsive layer is: the
 * artifact sets colour in inline style attributes, which outrank a stylesheet.
 * Without it the <p> rules silently do nothing while the inherited ones work,
 * which is how this was first built wrong.
 * ═══════════════════════════════════════════════════════════════════════════ */

/* ── Baseline, and the fallback ───────────────────────────────────────────────
 * White with a tight warm edge. A shadow only darkens the pixels touching a
 * glyph, so the sun between letters keeps its full value. This is what any
 * browser without background-clip:text gets, and it is a real improvement on
 * its own — the clip below is the upgrade, never the thing being relied on.
 */
[data-lit] h1,
[data-lit] h2,
[data-lit] p,
[data-lit] span,
[data-lit] i {
  text-shadow: 0 1px 1px rgba(58, 22, 4, 0.55), 0 2px 10px rgba(58, 22, 4, 0.38) !important;
}

/* The faded alphas are the worst offenders and cost nothing to fix: at .46 over
   the sun the copy sits at 1.18:1, which is not text, it is a texture. */
[data-lit] p { color: rgba(255, 250, 244, 0.94) !important; }
[data-lit] i { color: rgba(255, 250, 244, 0.82) !important; }

/* ── The sun clip ─────────────────────────────────────────────────────────────
 * GUARDED, and the guard is load-bearing: these rules set the text fill to
 * transparent, so in a browser that applied the colour but not the clip the
 * hero copy would be INVISIBLE rather than merely low-contrast. Verified
 * rendering correctly in Chromium and WebKit.
 *
 * The circle is derived from --sunD, the SAME variable that sizes the disc, and
 * inset slightly inside its true radius so the ink never spills past the limb
 * onto the night sky. These two were hardcoded separately for one build and
 * immediately disagreed the moment the sun was resized for portrait: the copy
 * inked itself on the night sky and vanished.
 */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {

  [data-lit] h1,
  [data-lit] h2,
  [data-lit] p,
  [data-lit] span,
  [data-lit] i {
    /* Two layers, painted front to back. The sun is a circle CLIPPED AT THE
       HORIZON — the page paints night sky over everything below 62vh — so the
       circle alone is not the shape of the visible sun. The first layer is the
       horizon: transparent above it, opaque white below, which forces every
       glyph under the horizon back to white even though it is still inside the
       circle. The caption under the daily number sits exactly there, and it
       went ink-on-black before this layer existed. */
    background-image:
      linear-gradient(to bottom, transparent 0 62vh, #FFFAF4 62vh),
      radial-gradient(circle at 50vw var(--sun-center, 200vh),
                        #3B1A08 0 calc(var(--sunD) * 0.485),
                        #FFFAF4   calc(var(--sunD) * 0.485)) !important;
    background-attachment: fixed, fixed !important;
    -webkit-background-clip: text !important;
    background-clip: text !important;
    color: transparent !important;
    -webkit-text-fill-color: transparent !important;
    text-shadow: none !important;
  }

  /* "today" is the one accent on the page and it keeps its gold — but it has to
     obey the same light as everything else. Two layers: the sun's disc painted
     as ink ON TOP, transparent everywhere else, over the original warm gradient
     underneath. Off the sun you get the gold; the moment the sun rises behind
     it, the word goes ink, exactly like the white copy around it.
     The layers use DIFFERENT attachments on purpose: the ink layer is fixed so
     it tracks the sun, the gold layer scrolls with the element so the gradient
     still runs across the word as authored. */
  [data-lit] em {
    background-image:
      radial-gradient(circle at 50vw var(--sun-center, 200vh),
                      #3B1A08 0 calc(var(--sunD) * 0.485),
                      transparent calc(var(--sunD) * 0.485)),
      linear-gradient(96deg, #FFD489, #FF7A5B 58%, #FF6B5B) !important;
    background-attachment: fixed, scroll !important;
    -webkit-background-clip: text !important;
    background-clip: text !important;
    color: transparent !important;
    -webkit-text-fill-color: transparent !important;
  }

  /* At 150-200 weight the strokes are hairlines. Ink on a bright ground can
     carry slightly more body without changing the type's character. */
  [data-lit] h1, [data-lit] h2 { font-weight: 300 !important; }
  [data-lit] p                 { font-weight: 440 !important; }

  /* --sun-center only exists once the hero script has painted a frame. Until
     then the fallback of 200vh puts the whole circle far below the viewport, so
     every glyph resolves to the white stop and nothing flashes dark. */
}

/* Reduced motion stops the sun animating, but it still renders, so the clip is
   still correct. Nothing to undo here — noted so nobody adds an override. */

/* ── The daily number's label, on a portrait screen ───────────────────────────
 * --b4band is already defined as max(sunTop,0) + horizon, so centring in it
 * centres the group on the VISIBLE cap of the sun. That is correct and needs no
 * help. What breaks on a narrow screen is only the label: "Yours to spend
 * today" wraps to two lines, grows upward out of the disc, and ends up split
 * across the limb mid-word.
 *
 * Keep it on one line and it stays inside the disc.
 *
 * 🔴 Do NOT "fix" this with a transform on the block. A transform on an ancestor
 * makes background-attachment:fixed resolve against that element instead of the
 * viewport, which silently breaks the sun clip for everything inside it. That
 * was tried, and the ink stopped tracking the sun.
 */
@media (max-aspect-ratio: 1 / 1) {
  [data-beat="4"] > p {
    white-space: nowrap !important;
    font-size: 12px !important;
    /* Clear of the limb, not across it. The label is absolutely positioned at
       bottom:100% of the block, so this moves only the label and leaves the
       numeral centred on the visible cap. */
    margin-bottom: 30px !important;
  }
}
