/* Marketing site stylesheet.

   Lifted verbatim out of the inline <style> block in index.html. It was 432
   lines repeated in the HTML of every page that looks like the site, which meant
   a colour or a spacing fix had to be made in each of them and drifted between
   them. Same reasoning as app/hub.css: no build step here, so a plain stylesheet
   is the only way to have it exist once.

   The palette is gone from the top of this file. It lives in /tokens.css now,
   which every surface links, so the site, the athlete app and the coach hub
   cannot disagree about what --red is.

   Versioned in the link, the same as dq-core.js and hub.css, because Cloudflare
   serves assets with a long max-age and a new layout against an old stylesheet
   looks broken rather than stale. */

  *{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent}
  html{scroll-behavior:smooth}
  body{background:var(--ink); color:var(--bone); font-family:'Barlow',system-ui,sans-serif;
    line-height:1.55; -webkit-font-smoothing:antialiased; overflow-x:hidden}
  ::selection{background:var(--red); color:var(--white)}
  a{color:inherit; text-decoration:none}
  .wrap{max-width:1140px; margin:0 auto; padding:0 clamp(20px,5vw,48px)}

  /* faint vertical measure lines, a "platform" motif, not a gradient wash */
  /* Intentionally in three places: site.css, tool.css and guides/guide.css each
     carry this rule and they must stay identical. There is no shared stylesheet
     that all three reach except tokens.css, and tokens.css says in its own header
     that it holds no component or layout rules, which this is. A fourth file for
     one pseudo-element would be worse than a duplicate with a note on it.
     If you change it here, change it in the other two. */
  body::before{content:""; position:fixed; inset:0; pointer-events:none; z-index:0;
    background-image:linear-gradient(90deg, var(--line) 1px, transparent 1px);
    background-size:clamp(60px,9vw,110px) 100%; background-position:center; opacity:.5;
    -webkit-mask-image:linear-gradient(180deg, transparent, #000 20%, #000 80%, transparent);
            mask-image:linear-gradient(180deg, transparent, #000 20%, #000 80%, transparent)}
  /* What sits ABOVE the lines. The pseudo-element is fixed at z-index:0, so
     anything not lifted here is painted over rather than behind, and this list
     was a different set of elements in each of the three files. The breadcrumb
     was in none of them: it is a bare <div class="wrap"> between the topbar and
     the hero, so on fourteen pages the motif was drawn on top of it. Faint, but
     it is the one place on the site where the texture was in front of the words. */
  header,section,nav,footer,.crumb{position:relative; z-index:1}

  /* ===== NAV ===== */
  .topbar{position:sticky; top:0; z-index:60; background:rgba(12,12,14,.8); backdrop-filter:blur(16px);
    border-bottom:1px solid var(--line)}
  .topbar .wrap{display:flex; align-items:center; justify-content:space-between; height:68px}
  .logo{display:flex; align-items:center; gap:12px}
  .logo .mark{width:40px; height:40px; background:linear-gradient(145deg,var(--red-hot),var(--red-deep)); display:grid; place-items:center;
    clip-path:polygon(0 0,100% 0,100% 72%,72% 100%,0 100%)}
  .logo .mark span{font-family:'Oswald'; font-weight:700; font-size:19px; color:#fff; letter-spacing:.02em}
  .logo b{font-family:'Oswald'; font-weight:600; letter-spacing:.06em; font-size:17px; text-transform:uppercase; line-height:1}
  .logo small{display:block; font-family:'JetBrains Mono'; font-size:8px; color:var(--grey); letter-spacing:.22em; margin-top:6px; line-height:1}
  .nav-r{display:flex; align-items:center; gap:4px}
  .nav-r a.link{font-family:'JetBrains Mono'; font-weight:500; font-size:11px; letter-spacing:.14em; text-transform:uppercase;
    color:var(--grey); padding:9px 13px}
  .nav-r a.link:hover{color:var(--white)}
  /* Skip link. Every page starts with a logo and five nav links, so without
     this a keyboard or screen reader user tabs through the whole header on
     every single page before reaching anything they came for. Positioned off
     screen rather than display:none, because display:none also removes it from
     the tab order. */
  .skip{position:absolute; left:-9999px; top:0; z-index:100;
    background:var(--red); color:#fff; padding:14px 20px; min-height:44px;
    font-family:'Oswald',sans-serif; font-weight:600; font-size:13px;
    letter-spacing:.08em; text-transform:uppercase; text-decoration:none}
  .skip:focus{left:0}
  .btn{font-family:'Oswald'; font-weight:600; font-size:12px; letter-spacing:.1em; text-transform:uppercase;
    padding:12px 20px; cursor:pointer; border:1px solid transparent; display:inline-block; transition:.16s}
  .btn-red{background:var(--red); color:#fff}
  .btn-red:hover{background:var(--red-hot)}
  .btn-ghost{border-color:var(--line-red-soft); color:var(--bone)}
  .btn-ghost:hover{border-color:var(--red); color:#fff; background:rgba(192,57,43,.08)}
  /* Athlete Login is solid white on purpose. Red belongs to "Work with DQ",
     which is the thing that earns money, and gold now means "free" everywhere
     else on the site. White is the highest contrast left on a near-black
     header, so the login stands out more than the old outline did without
     competing with the primary action. Red is become a customer, white is you
     already are one. */
  .btn-white{background:#fff; color:#0C0C0E; border-color:#fff}

/* The Instagram line under the coach portrait. Gold, because gold means "free"
   everywhere else here and red is reserved for "become a customer", and this is
   neither a purchase nor a paid thing. 44px so it is a real tap target on a
   phone rather than a 13px line of text somebody has to aim at. */
.pcap{margin-top:10px; text-align:center}
.pcap a{display:inline-flex; align-items:center; justify-content:center;
  min-height:44px; padding:0 6px; font-family:'JetBrains Mono'; font-size:11.5px;
  letter-spacing:.1em; text-transform:uppercase; color:var(--gold);
  border-bottom:1px solid transparent}
.pcap a:hover{color:var(--white); border-bottom-color:var(--gold)}
  .btn-white:hover{background:var(--bone); color:#0C0C0E}
  #navAuth{display:inline-flex; align-items:center; gap:9px}
  #navAuth .who{font-family:'JetBrains Mono'; font-size:10px; letter-spacing:.1em; text-transform:uppercase;
    color:var(--gold); white-space:nowrap}
  @media(max-width:640px){#navAuth .who{display:none}}
  /* Below 640 the links are already hidden and the sticky enquire bar takes
     over, so a second button here would just crowd the logo. */
  @media(max-width:640px){.nav-r a.link{display:none} .nav-cta{display:none}}

  /* ===== HERO (asymmetric) ===== */
  .hero{padding:clamp(44px,7vw,88px) 0 clamp(36px,5vw,60px)}
  .hero-grid{display:grid; grid-template-columns:1.55fr 1fr; gap:clamp(28px,5vw,64px); align-items:end}
  @media(max-width:900px){.hero-grid{grid-template-columns:1fr; align-items:start}}
  .eyebrow{font-family:'JetBrains Mono'; font-size:11px; letter-spacing:.3em; text-transform:uppercase; color:var(--red-hot);
    display:flex; align-items:center; gap:12px; margin-bottom:24px}
  .eyebrow::before{content:""; width:30px; height:2px; background:var(--red); flex:none}
  /* keep "UK-wide" from breaking at its own hyphen on a narrow phone */
  .nb{white-space:nowrap}
  .hero h1{font-family:'Oswald'; font-weight:700; text-transform:uppercase; line-height:.9;
    font-size:clamp(52px,10vw,120px); letter-spacing:.003em; margin-bottom:22px}
  .hero h1 .stroke{color:transparent; -webkit-text-stroke:2px var(--red); display:inline-block}
  .hero p.lead{font-size:clamp(16px,2.1vw,20px); color:var(--bone); max-width:46ch; margin-bottom:30px}
  .hero .cta-row{display:flex; gap:12px; flex-wrap:wrap}
  .hero .btn{padding:15px 28px; font-size:13px}
  /* Right hand hero column. Bottom aligned so the block sits level with the
     call to action on the left. */
  .hero-right{display:flex; flex-direction:column; gap:14px; justify-content:flex-end}
  /* One big gold block rather than a bordered panel with a small caption. DQ
     asked for the free tools to read as a button, with the guides sitting
     directly under it as the second door. */
  .freebox{display:block; border:1px solid rgba(201,162,39,.45); background:rgba(201,162,39,.06);
    padding:18px 20px; margin-bottom:12px; transition:.2s}
  .freebox:hover{border-color:var(--gold); background:rgba(201,162,39,.13)}
  .freebox b{display:block; font-family:'Oswald'; font-weight:600; text-transform:uppercase;
    letter-spacing:.04em; font-size:22px; color:var(--gold); line-height:1}
  .freebox span{display:block; margin-top:7px; font-size:12.5px; color:#A7A4A0; line-height:1.5}
  /* Separate box, in the site's own red rather than gold, so the two read as
     two doors instead of one long panel. */
  .guidebox{display:block; border:1px solid var(--line-red-soft); padding:18px 20px;
    background:linear-gradient(180deg,rgba(192,57,43,.08),rgba(192,57,43,.02)); transition:.18s}
  .guidebox:hover{border-color:var(--red); background:rgba(192,57,43,.14)}
  .guidebox b{display:block; font-family:'Oswald'; font-weight:600; text-transform:uppercase;
    letter-spacing:.05em; font-size:22px; line-height:1; color:var(--bone)}
  .guidebox:hover b{color:var(--red-hot)}
  .guidebox span{display:block; margin-top:7px; font-size:12.5px; color:#A7A4A0; line-height:1.5}
  /* Below the hero split this stacks under the headline, which is where it
     should be on a phone anyway. */
  @media(max-width:900px){.hero-right{gap:16px}}

  /* ===== SECTION SHELL ===== */
  section{padding:clamp(42px,6vw,80px) 0; border-top:1px solid var(--line)}
  /* the topbar is sticky and 68px tall, so an anchor jump used to land with the
     section eyebrow sliced in half. Every jump target clears it. */
  section,header{scroll-margin-top:84px}
  .sec-eyebrow{font-family:'JetBrains Mono'; font-size:11px; letter-spacing:.28em; text-transform:uppercase; color:var(--red-hot); margin-bottom:16px; display:inline-flex; align-items:center; gap:11px}
  .sec-eyebrow::before{content:""; width:24px; height:2px; background:var(--red); flex:none}
  .sec-title{font-family:'Oswald'; font-weight:600; text-transform:uppercase; letter-spacing:.02em;
    font-size:clamp(30px,5vw,54px); line-height:.98; margin-bottom:18px}

  /* Reveal on scroll. Gated on html.js, which the inline script in the head sets.
     It used to be an unconditional opacity:0, so if the observer script failed, was
     blocked, or threw before it ran, everything below the hero was invisible and the
     page looked empty rather than un-animated. */
  html.js .rv{opacity:0; transform:translateY(16px); transition:opacity .6s ease, transform .6s ease}
  html.js .rv.in{opacity:1; transform:none}

  /* ===== ABOUT ===== */
  /* The heading spans both columns, so the photo and the timeline start on the
     same line without a magic top offset. The row stretches, and the timeline
     is a flex column spread over that height, so its red bar runs the full
     height of the photo rather than stopping two thirds of the way down. */
  .about-head{margin-bottom:26px}
  .about-grid{display:grid; grid-template-columns:minmax(0,420px) 1fr; gap:clamp(28px,5vw,64px); align-items:stretch}
  @media(max-width:860px){.about-grid{grid-template-columns:1fr; align-items:start}}
  .lineage-col{display:flex}
  /* lineage timeline, real sequence, so numbering is earned */
  .lineage{border-left:1px solid var(--line-red-soft); padding-left:22px; display:flex; flex-direction:column;
    gap:18px; flex:1; justify-content:space-between}
  @media(max-width:860px){.lineage{flex:none; justify-content:flex-start}}
  .ln{position:relative}
  .ln::before{content:""; position:absolute; left:-29px; top:4px; width:9px; height:9px; background:var(--red); border-radius:50%; box-shadow:0 0 0 4px var(--ink)}
  .ln .yr{font-family:'JetBrains Mono'; font-size:10px; letter-spacing:.14em; color:var(--red-hot); text-transform:uppercase}
  .ln h3{font-family:'Oswald'; font-weight:500; text-transform:uppercase; font-size:17px; letter-spacing:.02em; margin:4px 0 3px}
  .ln p{font-size:13px; color:var(--grey); max-width:42ch}
  .ln p a{color:var(--bone); border-bottom:1px solid var(--line-red-soft)}
  .ln p a:hover{color:var(--red-hot)}

  /* ===== CREDENTIALS, columns ===== */
  .cred-cols{display:grid; grid-template-columns:repeat(4,minmax(240px,1fr)); gap:12px; margin-top:52px;
    padding-top:44px; border-top:1px solid var(--line)}
  /* The swipe hint carries the divider whenever it is visible, and .cred-cols
     gives it up, so the line above this block is drawn exactly once at every
     width. Hidden by default rather than shown, because the grid only becomes a
     rail below 1100px and the hint would otherwise be pointing at four cards
     that are all already on screen.

     Written as .app-hint.cred-hint, not .cred-hint. `.app-hint{display:flex}`
     is declared further down this file, and against a single class it simply
     wins on order, so the hint drew at every width. Both halves are qualified
     for the same reason, including the one below that happened to work: it only
     worked because .app-hint's flex was what showed it, which is the right
     answer arrived at by accident. */
  .app-hint.cred-hint{display:none}
  /* Four cards do not fit at any sane column width, so below 1100 they become a
     rail that scrolls sideways rather than a grid that squeezes. */
  @media(max-width:1100px){
    .cred-cols{grid-auto-flow:column; grid-auto-columns:minmax(260px,80vw); grid-template-columns:none;
      overflow-x:auto; scroll-snap-type:x mandatory; -webkit-overflow-scrolling:touch;
      padding-bottom:10px;
      margin-left:calc(clamp(20px,5vw,48px) * -1); margin-right:calc(clamp(20px,5vw,48px) * -1);
      padding-left:clamp(20px,5vw,48px); padding-right:clamp(20px,5vw,48px)}
    .cred-col{scroll-snap-align:start}
    .app-hint.cred-hint{display:flex; margin-top:52px; padding-top:44px; border-top:1px solid var(--line)}
    .cred-cols{margin-top:18px; padding-top:0; border-top:none}
  }
  .cred-col{position:relative; background:linear-gradient(180deg,var(--coal2),var(--coal)); border:1px solid var(--line); border-top:2px solid var(--red);
    padding:20px 20px; transition:transform .25s ease, border-color .25s ease, box-shadow .25s ease}
  .cred-col:hover{transform:translateY(-4px); border-color:var(--line-red-soft); border-top-color:var(--red-hot); box-shadow:0 18px 40px -20px rgba(0,0,0,.8)}
  .cc-head{margin-bottom:14px}
  .cc-head h3{font-family:'Oswald'; font-weight:600; text-transform:uppercase; letter-spacing:.03em; font-size:21px; color:var(--gold)}
  .cc-head .body-tag{display:block; font-family:'JetBrains Mono'; font-size:9px; letter-spacing:.1em; color:var(--red-hot); margin-top:6px; text-transform:uppercase}
  .cc-intro{font-size:13px; color:var(--grey); line-height:1.5; margin-bottom:14px; padding-bottom:14px; border-bottom:1px solid var(--line)}
  .cc-list{list-style:none}
  .cc-list li{padding:9px 0 9px 20px; position:relative; border-bottom:1px solid rgba(255,255,255,.03)}
  .cc-list li:last-child{border-bottom:none}
  .cc-list li::before{content:""; position:absolute; left:0; top:15px; width:7px; height:7px; background:var(--red); transform:rotate(45deg); transition:background .2s}
  .cred-col:hover .cc-list li::before{background:var(--red-hot)}
  .cc-list li b{display:block; font-family:'Barlow'; font-weight:700; font-size:14.5px; color:var(--bone); line-height:1.3}
  .cc-list li span{display:block; font-size:12px; color:var(--grey); margin-top:3px; line-height:1.45}
  /* CPD entries are names with nothing under them, so they can sit tighter.
     The 20px left padding stays: that is the room the diamond marker needs. */
  .cc-cpd li{padding:7px 0 7px 20px}
  .cc-cpd li::before{top:13px}
  .cc-cpd b{font-weight:600; font-size:13.5px}

  /* ===== DISCIPLINES ===== */
  .disc-cards{display:grid; grid-template-columns:repeat(3,1fr); gap:16px}
  @media(max-width:760px){.disc-cards{grid-template-columns:1fr}}
  .dcard{position:relative; background:linear-gradient(180deg,var(--coal2),var(--coal)); border:1px solid var(--line); padding:26px;
    transition:transform .25s ease, border-color .25s ease, box-shadow .25s ease; overflow:hidden}
  .dcard::after{content:""; position:absolute; left:0; top:0; width:100%; height:2px; background:var(--red); transform:scaleX(0); transform-origin:left; transition:transform .3s ease}
  .dcard:hover{transform:translateY(-4px); border-color:var(--line-red-soft); box-shadow:0 18px 40px -20px rgba(0,0,0,.8)}
  .dcard:hover::after{transform:scaleX(1)}
  .dcard .idx{font-family:'JetBrains Mono'; font-size:11px; color:var(--grey-d); letter-spacing:.1em}
  .dcard h3{font-family:'Oswald'; font-weight:600; text-transform:uppercase; font-size:21px; letter-spacing:.03em; margin:10px 0 12px}
  .dcard p{color:var(--grey); font-size:14px; line-height:1.55}
  .dcard{display:flex; flex-direction:column}
  .dcard .dmore{margin-top:auto; padding-top:16px; font-family:'JetBrains Mono'; font-size:10px;
    letter-spacing:.14em; text-transform:uppercase; color:var(--red-hot)}
  .dcard:hover .dmore{color:var(--gold)}
  /* DQ wanted these to look like doors. The label now sits in a bordered
     block that fills on hover, the same shape as every other card link here. */
  .dcard .dmore{display:inline-flex;align-items:center;align-self:flex-start;margin-top:auto;
    border:1px solid rgba(201,162,39,.45);padding:10px 16px;min-height:44px;
    font-family:'JetBrains Mono';font-size:10px;letter-spacing:.14em;text-transform:uppercase;
    transition:.18s}
  .dcard:hover .dmore{background:rgba(201,162,39,.14);border-color:var(--gold);color:var(--gold)}

  /* ===== ENQUIRY ===== */
  .enq-grid{display:grid; grid-template-columns:1fr 1.1fr; gap:clamp(28px,5vw,60px); align-items:start}
  @media(max-width:860px){.enq-grid{grid-template-columns:1fr}}
  .enq-left p{color:var(--grey); margin-bottom:20px; max-width:42ch}
  /* the form used to be the only way in. If Formspree is blocked or down, this is the fallback. */
  .enq-left .enq-alt{margin-top:20px; font-size:14px; color:var(--grey); max-width:42ch}
  .enq-left .enq-alt a{color:var(--bone); border-bottom:1px solid var(--line-red-soft)}
  .enq-left .enq-alt a:hover{color:var(--red-hot)}
  /* The inline form moved to /assessment. This is the card that points at it. */
  .assess-card{background:var(--coal); border:1px solid var(--line-red-soft); padding:28px}
  /* The short form is back as the way in. The assessment still exists at
     /assessment and is what DQ sends once somebody is actually interested, but
     asking for six sections before a first hello was a gate on an enquiry. */
  .enqform{display:grid; gap:13px}
  .enqform .row2{display:grid; grid-template-columns:1fr 1fr; gap:13px}
  @media(max-width:520px){.enqform .row2{grid-template-columns:1fr}}
  .enqform label{display:block; font-family:'JetBrains Mono'; font-size:10px; letter-spacing:.1em;
    text-transform:uppercase; color:var(--grey); margin-bottom:6px}
  .enqform input,.enqform select,.enqform textarea{width:100%; background:var(--ink);
    border:1px solid var(--line); color:var(--bone); padding:12px 14px;
    font-family:'Barlow',system-ui,sans-serif; font-size:16px}
  .enqform textarea{min-height:96px; resize:vertical}
  .enqform input:focus,.enqform select:focus,.enqform textarea:focus{outline:none;
    border-color:var(--red); box-shadow:0 0 0 3px rgba(192,57,43,.16)}
  .enqform .btn{padding:15px 28px; font-size:13px; justify-self:start}
  .enq-ok{display:none; border:1px solid var(--line-red-soft);
    background:linear-gradient(180deg,rgba(192,57,43,.08),rgba(192,57,43,.02)); padding:24px}
  .enq-ok.on{display:block}
  .enq-ok b{display:block; font-family:'Oswald'; font-weight:600; text-transform:uppercase;
    letter-spacing:.03em; font-size:21px; margin-bottom:10px}
  .enq-ok p{font-size:15px; line-height:1.7; color:var(--bone)}
  .enq-ok .nx{margin-top:16px; font-size:14px; color:#A7A4A0}
  .enq-ok .nxl{margin:12px 0 0; padding-left:0; list-style:none}
  .enq-ok .nxl li{font-size:14px; line-height:1.65; color:#A7A4A0; padding:10px 0 10px 18px;
    position:relative; border-top:1px solid var(--line)}
  .enq-ok .nxl li::before{content:""; position:absolute; left:0; top:17px; width:5px; height:5px;
    background:var(--red); transform:rotate(45deg)}
  .enq-ok .nxl a{color:var(--bone); text-decoration:underline; text-underline-offset:3px}
  .enq-ok .nxl a:hover{color:var(--red-hot)}
  .assess-card .ac-h{font-family:'Oswald'; font-weight:600; text-transform:uppercase;
    letter-spacing:.04em; font-size:20px; color:var(--bone); margin-bottom:12px}
  .assess-card .btn{width:100%; padding:16px; font-size:13px; text-align:center}
  form .btn{width:100%; padding:15px; font-size:13px; margin-top:4px}
  /* was --grey-d at 10px, which measured 2.68:1 and failed WCAG AA. This is the
     line that reassures someone with their finger over the submit button, so it
     has to be readable. --grey at 11px measures 5.69:1. */
  /* .form-ok is gone. index.html is the only page that links this file and its
     enquiry confirmation is .enq-ok, styled above, so these four rules had no
     element to match. The live .form-ok is an inline copy on /assessment,
     /privacy and /terms, which do not link site.css. Removed here rather than
     given a weight, because .form-ok .big was one of the five unweighted Oswald
     selectors this pass set out to fix and weighting a dead rule is a change
     that reads as one. */

  /* ===== FOOTER ===== */
  footer{border-top:1px solid var(--line); padding:40px 0 calc(40px + var(--safe-b))}
  footer .wrap{display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:16px}
  footer .flink{color:var(--white); text-decoration:underline; text-underline-offset:3px;
    display:inline-block; padding:8px 2px}
  footer .flink:hover{color:var(--red-hot)}
  footer .discs{font-family:'Oswald'; font-weight:300; font-size:11px; letter-spacing:.16em; text-transform:uppercase; color:var(--red-hot); display:flex; gap:14px; flex-wrap:wrap}
  /* Under the 24px WCAG AA minimum as bare text, so each link gets its own
     padding rather than the row being made taller. */
  footer .discs a{display:inline-block; padding:8px 0}
  footer small{font-family:'JetBrains Mono'; font-size:11px; color:var(--grey-d)}

  @media(prefers-reduced-motion:reduce){*{animation:none!important; transition:none!important; scroll-behavior:auto!important}html.js .rv{opacity:1;transform:none}}

  /* ===== coach portrait ===== */
  .portrait{position:relative; margin:0; max-width:420px; width:100%; align-self:start}
  .portrait picture{display:block}
  .portrait img{width:100%; height:auto; display:block; aspect-ratio:3/4; object-fit:cover; object-position:center 38%;
    clip-path:polygon(0 0,100% 0,100% 90%,90% 100%,0 100%);
    /* Graded in CSS rather than baked into the file. Re-encoding the 900 wide
       source came out at 206KB against the 98KB webp it would have replaced,
       which is a bad trade on the asset that matters most on a phone. The
       filter costs nothing to download. Slightly more contrast, a little
       saturation out of the loud bumper plates, and a touch of warmth so it
       sits with the near-black page rather than against it. */
    filter:contrast(1.09) saturate(0.88) brightness(0.99) sepia(0.06)}
  .portrait::after{content:""; position:absolute; left:0; bottom:0; width:46px; height:3px; background:var(--red)}
  @media(max-width:860px){.portrait{max-width:300px}}
  /* ===== how it works ===== */
  .steps{display:grid; grid-template-columns:repeat(auto-fit,minmax(230px,1fr)); gap:18px; margin-top:26px}
  .step{border:1px solid var(--line); background:linear-gradient(180deg,var(--coal),var(--ink)); padding:22px 20px; position:relative}
  .step::before{content:""; position:absolute; top:0; left:0; right:0; height:2px; background:var(--red)}
  .step .no{font-family:'JetBrains Mono'; font-size:10px; letter-spacing:.2em; color:var(--red-hot)}
  .step h3{font-family:'Oswald'; font-weight:600; text-transform:uppercase; letter-spacing:.03em; font-size:17px; margin:10px 0 8px}
  .step p{font-size:14px; color:#A7A4A0; line-height:1.6}

  /* ===== the app band ===== */
  #theapp{background:linear-gradient(180deg,#08080A,#0C0C0E 40%,#08080A);border-top:1px solid rgba(255,255,255,.06);border-bottom:1px solid rgba(255,255,255,.06);padding:74px 0 66px;overflow:hidden}
  #theapp .wrap{max-width:1180px}
  /* current integrations, listed apart from the prose so the list can grow */
  .integrations{display:flex;align-items:center;gap:16px;flex-wrap:wrap;margin-top:24px;
    border:1px solid rgba(201,162,39,.45);background:rgba(201,162,39,.07);padding:16px 20px}
  .integrations .ig-label{font-family:'JetBrains Mono';font-size:10px;letter-spacing:.18em;
    text-transform:uppercase;color:var(--gold);flex:none}
  .integrations .ig-list{display:flex;gap:10px;flex-wrap:wrap}
  .integrations .ig-list span{font-family:'Oswald';font-weight:600;font-size:12px;letter-spacing:.06em;
    text-transform:uppercase;color:var(--bone);border:1px solid rgba(201,162,39,.4);padding:6px 12px;
    background:rgba(12,12,14,.5)}
  .integrations .ig-list span.soon{color:var(--grey);border-style:dashed;border-color:var(--coal3)}
  .shot-rail{display:flex;gap:20px;overflow-x:auto;overflow-y:hidden;padding:22px 0;margin-top:0;scroll-snap-type:x mandatory;scroll-padding-left:0;-webkit-overflow-scrolling:touch}
  .shot{flex:0 0 auto;width:250px;scroll-snap-align:start}
  .shot .frame{aspect-ratio:780/1600;overflow:hidden;border:6px solid #202024;background:#0C0C0E;border-radius:34px;box-shadow:0 18px 40px rgba(0,0,0,.55);transition:transform .25s ease,border-color .25s ease}
  .shot:hover .frame{transform:translateY(-6px);border-color:rgba(192,57,43,.45)}
  .shot img{display:block;width:100%;height:100%;object-fit:cover;object-position:top;border-radius:27px}
  .shot .cap{margin-top:14px}
  .shot .cap b{display:block;font-family:'Oswald',sans-serif;font-weight:600;text-transform:uppercase;letter-spacing:.04em;font-size:13.5px;color:var(--bone)}
  .shot .cap span{display:block;margin-top:5px;font-size:13px;line-height:1.55;color:#8A8A90}
  /* the swipe hint used to sit under the rail, which is the one place a reader
     has already scrolled past by the time they need it. It sits above it now. */
  .app-hint{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--gold);margin-top:24px;display:flex;align-items:center;gap:10px}
  .app-hint::after{content:"";flex:1;height:1px;background:linear-gradient(90deg,rgba(201,162,39,.35),transparent);max-width:180px}
  @media(max-width:640px){ .shot{width:210px} #theapp{padding:56px 0 50px} }
  /* ===== pricing ===== */
  .tiers{display:grid; grid-template-columns:repeat(auto-fit,minmax(250px,1fr)); gap:14px; margin-top:20px; align-items:start}
  .tier{border:1px solid var(--line); background:linear-gradient(180deg,var(--coal),var(--ink)); padding:22px 20px; display:flex; flex-direction:column; position:relative}
  .tier.feat{border-color:rgba(192,57,43,.4)}
  .tier.feat::before{content:"Most chosen"; position:absolute; top:-1px; right:16px; background:var(--red); color:#fff;
    font-family:'JetBrains Mono'; font-size:8.5px; letter-spacing:.14em; text-transform:uppercase; padding:5px 10px}
  .tier h3{font-family:'Oswald'; font-weight:600; text-transform:uppercase; letter-spacing:.04em; font-size:18px}
  .tier .price{font-family:'Oswald'; font-weight:600; font-size:38px; margin:14px 0 2px; line-height:1}
  .tier .price span{font-size:14px; color:var(--grey); font-weight:400}
  .tier .from{font-family:'JetBrains Mono'; font-size:9px; letter-spacing:.14em; color:var(--gold); text-transform:uppercase}
  /* material terms belong next to the price, not only in the note underneath */
  .tier .term{font-family:'JetBrains Mono'; font-size:9px; letter-spacing:.12em; text-transform:uppercase;
    color:var(--grey); margin-top:8px}
  .tier ul{list-style:none; margin:16px 0 18px; padding:0}
  .tier li{font-size:14px; color:#A7A4A0; padding:6px 0 6px 20px; position:relative; border-top:1px solid rgba(255,255,255,.04); line-height:1.5}
  .tier li:first-child{border-top:none}
  .tier li::before{content:""; position:absolute; left:0; top:13px; width:7px; height:7px; background:var(--red); transform:rotate(45deg)}
  .price-note{margin-top:22px; font-size:12px; color:var(--grey); padding:0; background:none;
    border:0; line-height:1.7; max-width:70ch}
  .price-note .ast{color:var(--red-hot); margin-right:5px}

  /* The FAQ and "who this is not for" sections were both removed from the home
     page (see docs/backlog.md, "Deleted from the home page"). Their rules,
     .faq* and .fit*, went with them: index.html carries neither element any
     more and site.css is the only page that links this file, so nothing here
     was reachable. Found while giving Oswald its weight ladder, because two of
     the dead declarations, .faq summary and .fit h3, were among the ones this
     pass was fixing. Removed rather than fixed for that reason. */

  /* ===== mid-page calls to action =====
     There used to be exactly one button between the hero and the form at the
     bottom of the page, so a visitor convinced by the app or the credentials had
     nowhere to act. One of these closes each section that does persuading. */
  .cta-strip{margin-top:34px; border:1px solid var(--line-red-soft); background:linear-gradient(180deg,rgba(192,57,43,.07),rgba(192,57,43,.02));
    padding:20px 22px; display:flex; align-items:center; justify-content:space-between; gap:18px; flex-wrap:wrap}
  .cta-strip p{margin:0; font-size:15px; color:var(--bone); max-width:52ch; line-height:1.55}
  .cta-strip .btn{flex:none; padding:13px 24px}
  @media(max-width:560px){ .cta-strip{flex-direction:column; align-items:stretch} .cta-strip .btn{text-align:center} }

  /* ===== sticky enquire bar, phones only =====
     Hidden until the visitor is past the hero, and hidden again once the real
     form is on screen so it never covers the thing it is pointing at. */
  .enq-bar{position:fixed; left:0; right:0; bottom:0; z-index:70; display:none;
    background:rgba(12,12,14,.94); backdrop-filter:blur(14px); border-top:1px solid var(--line-red-soft);
    padding:10px 16px calc(10px + var(--safe-b)); align-items:center; gap:12px;
    transform:translateY(110%); transition:transform .28s ease}
  .enq-bar.show{transform:none}
  .enq-bar .lbl{flex:1; min-width:0; font-family:'JetBrains Mono'; font-size:10px; letter-spacing:.12em;
    text-transform:uppercase; color:var(--grey); line-height:1.5}
  .enq-bar .lbl b{display:block; font-family:'Barlow'; font-weight:600; font-size:14px; letter-spacing:0;
    text-transform:none; color:var(--bone)}
  .enq-bar .btn{flex:none; padding:13px 20px}
  @media(max-width:760px){ .enq-bar{display:flex} body{padding-bottom:74px} }
  @media(max-width:760px) and (prefers-reduced-motion:reduce){ .enq-bar{transition:none} }

/* ===========================================================================
   Homepage finish pass. Ten changes, all surface.

   Append this to the END of site.css, or keep it as its own file and link it
   after site.css. It is append-only on purpose: every rule here either targets
   a property the original never set, or repeats a selector so it wins on order
   rather than on specificity. Nothing above it has to be edited, so this cannot
   conflict with anything landing upstream at the same time.

   No markup is touched and no geometry changes: only fill, border, shadow,
   state and one type property. Nothing can reflow, and scripts/audit.js cannot
   see a difference.

   Scope: every page that links site.css, which today is index.html. The athlete
   app and the coach hub are untouched, and so is the login screen.

   Bump the version in the link when this lands: site.css?v2.
   =========================================================================== */

/* 01. Cards look lit rather than cut out.
   A 7 percent border on near-black reads as a hole in the page. A one pixel
   inset highlight gives the card a top edge, and 10 percent gives it a visible
   boundary at phone brightness. The fill becomes the same 180 degree gradient
   the discipline cards already use, so the panels on this page stop disagreeing
   with each other about what a card is. */
.cred-col,.step,.tier,.assess-card{
  border-color:rgba(255,255,255,.1);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.05);
}
.assess-card{background:linear-gradient(180deg,#17171B,#121215)}

/* 02. The primary button gets the mark's material.
   Every red button is flat #C0392B while the mark in the header is a 145 degree
   gradient from #E74C3C. Same gradient, plus a top highlight and a one pixel
   base shadow, so the one action that earns money looks pressable and belongs
   to the logo. Hover is unchanged: it still goes brighter, not darker. */
.btn-red{
  background:linear-gradient(145deg,#D8422F,#B02F23);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.18),0 1px 0 rgba(0,0,0,.4);
}
.btn-red:hover{background:linear-gradient(145deg,#E74C3C,#C0392B)}

/* 03. The gold boxes carry a gold top rule.
   Red cards signal with a 2px rule across the top. The two gold boxes are the
   biggest doors in the hero and signal with nothing but a wash, so the free
   things read as a lighter afterthought. Same device, in gold. */
.freebox{
  background:linear-gradient(180deg,rgba(201,162,39,.11),rgba(201,162,39,.04));
  border-color:rgba(201,162,39,.5);
  box-shadow:inset 0 2px 0 rgba(201,162,39,.55);
}
.freebox:hover{
  background:linear-gradient(180deg,rgba(201,162,39,.17),rgba(201,162,39,.06));
  box-shadow:inset 0 2px 0 var(--gold);
}

/* 04. Inputs read as inset.
   The field is filled with the page colour while sitting on a card, so it
   currently disappears into it. A hair lighter than the page, a 12 percent
   border and a soft inner shadow makes it obviously a thing you type into. The
   red focus ring is deliberately left exactly as it is. */
.enqform input,.enqform select,.enqform textarea{
  background:#111114;
  border-color:rgba(255,255,255,.12);
  box-shadow:inset 0 1px 2px rgba(0,0,0,.5);
}
.enqform input:focus,.enqform select:focus,.enqform textarea:focus{
  box-shadow:inset 0 1px 2px rgba(0,0,0,.5),0 0 0 3px rgba(192,57,43,.16);
}

/* 05. The chosen tier looks chosen.
   Coaching is the tier to be on and it differs from the other two by a slightly
   redder border and a small tag. A red rule across its top and a low red-tinted
   glow give it hierarchy at a glance, without changing a price, a word or a
   position. The "Most chosen" tag still sits over the rule, as it does now. */
.tier.feat{
  border-color:rgba(192,57,43,.55);
  box-shadow:inset 0 2px 0 var(--red),0 18px 40px -24px rgba(192,57,43,.55);
}

/* 06. Figures line up.
   Oswald's default figures are proportional, so a column of prices sits very
   slightly ragged. One property, no size or position change. */
.tier .price,.tier .term{font-variant-numeric:tabular-nums}

/* 07. The red hover wipe, on the other card that lifts.
   The discipline cards wipe a 2px red rule in from the left on hover and it is
   the best interaction on the site. The credential columns already lift and
   change border on hover but do not wipe, so the same gesture behaves two ways.
   The rule is drawn on the element's existing red top border rather than added
   as a new one, so nothing grows by a pixel. */
.cred-col{position:relative;overflow:hidden}
.cred-col::after{
  content:"";position:absolute;left:0;top:0;width:100%;height:2px;
  background:var(--red-hot);transform:scaleX(0);transform-origin:left;
  transition:transform .3s ease;
}
.cred-col:hover::after{transform:scaleX(1)}

/* 08. Phone frames read as glass.
   The screenshot rail is the strongest thing on the page. A tighter, deeper
   shadow and a one pixel inner keyline make the frame read as a device with a
   screen in it rather than as a picture with a border. */
.shot .frame{
  border-color:rgba(255,255,255,.16);
  box-shadow:0 22px 50px -12px rgba(0,0,0,.75),inset 0 0 0 1px rgba(255,255,255,.06);
}
.shot:hover .frame{
  box-shadow:0 26px 54px -12px rgba(0,0,0,.8),inset 0 0 0 1px rgba(231,76,60,.25);
}

/* 09. Section seams get a shadow line.
   Sections divide on a single 7 percent hairline, which on an OLED phone at low
   brightness can disappear entirely. One pixel of near-black under the existing
   border reads as a machined seam at every brightness, and still measures as
   one line of division. */
section{box-shadow:inset 0 1px 0 rgba(0,0,0,.55)}
/* The app band already carries its own borders, so it keeps them. */
#theapp{box-shadow:none}

/* 10. Depth behind the headline.
   The measure lines go from 50 to 62 percent, so the platform motif is actually
   visible on a phone, and a low red radial sits behind the hero headline so the
   stroked word has something to be outlined against. This is the one change
   here with any risk of reading as a gradient wash, so it is at 10 percent and
   masked to the top left. Delete these two rules if you do not want it. */
body::before{opacity:.62}
.hero{background:radial-gradient(120% 90% at 18% 30%,rgba(192,57,43,.10),transparent 60%)}

/* Reduced motion: the two transitions added above are covered by the existing
   blanket rule in site.css, which switches every transition off. Nothing here
   animates on load. */

/* ---------- sideways rails ----------

   Anything that scrolls sideways gets a bar you can see. Measured rather than
   picked: --red-hot on a --coal2 track is 4.41:1, comfortably past the 3:1 that
   WCAG 2.1 SC 1.4.11 asks of a UI component. Brand --red on the same track is
   3.10:1, which passes and no more, so the hotter red is the one that survives
   an 8px bar on a phone.

   What was here before measured 1.75:1: a 60% red thumb over a 6% white track,
   both composited down onto a near-black section, which is a scrollbar you can
   only find if you already know it is there.

   Both syntaxes are set on purpose. scrollbar-width and scrollbar-color are
   what Firefox reads; the ::-webkit- pseudo-elements are what Chrome, Edge and
   Safari read. Set one and the other browser draws its own default, which on
   macOS is a near-invisible overlay and in Chrome is a light-scheme grey bar on
   a black page.

   Never display:none. These rails are the only affordance that there is more to
   the right, and only one of them has copy saying so. */
.shot-rail, .cred-cols{scrollbar-width:thin; scrollbar-color:var(--red-hot) var(--coal2)}
.shot-rail::-webkit-scrollbar, .cred-cols::-webkit-scrollbar{height:8px; width:8px}
.shot-rail::-webkit-scrollbar-track, .cred-cols::-webkit-scrollbar-track{background:var(--coal2)}
.shot-rail::-webkit-scrollbar-thumb, .cred-cols::-webkit-scrollbar-thumb{background:var(--red-hot)}
.shot-rail::-webkit-scrollbar-thumb:hover, .cred-cols::-webkit-scrollbar-thumb:hover{background:var(--red)}
/* ---------- the keyboard focus ring ----------

   One ring, every interactive thing, all three stylesheets. Before this,
   site.css had no blanket rule at all, so index.html, privacy and terms gave a
   keyboard user nothing on any link or button, while tool.css and guide.css
   each had their own and the two did not match.

   --bone, and that is measurement rather than taste. The ring has to land on
   four grounds: --ink 16.16:1, --coal 15.20:1, --coal2 13.93:1, and --red
   4.50:1, which is the one that matters because every "Work with DQ" button and
   every active discipline tab is solid --red. The old --red ring measured 1.00:1
   there, and --red-hot 1.42:1. Both were invisible on exactly the controls
   somebody tabbing the page is heading for. 3:1 is what WCAG 2.1 SC 1.4.11 asks
   of a focus indicator.

   :focus-visible, not :focus, so a mouse click does not leave a ring behind.

   Text inputs are deliberately not in this list. .enqform input:focus already
   swaps the border to --red and adds a 16% halo, it beats this rule on
   specificity anyway, and it is a better indicator for a box you are typing in
   than an outline around it.

   That sentence said .field until 19 August, when the whole orphaned .field
   system was deleted from this file. The reasoning is unchanged and the live
   selector is .enqform, which is what the only page linking this stylesheet
   actually uses. Corrected rather than left, because a comment naming a
   selector that no longer exists reads as a rule somebody has deleted by
   mistake. */
a:focus-visible, button:focus-visible, summary:focus-visible,
[tabindex]:focus-visible, [role="tab"]:focus-visible{
  outline:2px solid var(--bone);
  outline-offset:3px;
}

/* The skip link is the one thing that sits flush against the page edge: it
   parks at left:0 when focused, and body{overflow-x:hidden} would clip an
   outward ring off the left of the viewport. Inset instead. */
.skip:focus-visible{outline-offset:-3px}

/* ---------- the mark ----------

   The badge, the letters and the corner cut are all inside logo-mark.svg now, so
   the only thing CSS still owns is the box it sits in. Three things changed in
   the drawing: the Q tail lengthened so it clears the ring, which is the whole
   point (at header sizes the old mark read as DO); stroke weight 24 to 28 units
   so the letters hold at 32 and 40px; and a deeper corner cut.

   The letters are paths, so the header no longer waits for Oswald. On a cold
   load on gym signal it used to show two fallback-font letters in a red box.

   The gradient is kept as a SECOND background layer under the SVG, and that is
   deliberate rather than tidy. The patch as written used the background
   shorthand, which resets background-color as well as background-image, so if
   this CSS reached the edge before the SVG did the mark would not degrade to a
   red badge, it would be a transparent box with its letters already hidden by
   the rule below: a header with no logo at all. Layered, a missing SVG leaves
   exactly the badge that is live today. Found by the app lane, worth having.

   No !important anywhere. This block is appended after the rule it overrides in
   every file it goes into, so equal specificity and later position is enough,
   and an override that can itself be overridden is the kinder thing to leave. */
.logo .mark,.mark{
  background-image:url("/logo-mark.svg"),linear-gradient(145deg,var(--red-hot),var(--red-deep));
  background-position:center;
  background-size:100% 100%;
  background-repeat:no-repeat;
  clip-path:polygon(0 0,100% 0,100% 58%,58% 100%,0 100%);
  display:block;
  position:relative;
}

/* The inner <span>DQ</span> is drawn inside the SVG now, so the live text node is
   duplicate content. Hidden rather than deleted: no markup changes, and it stays
   available to a screen reader that ignores background images. Kept in the flow
   at 1px rather than display:none, which some readers skip entirely. */
.logo .mark span,.mark span{
  position:absolute;
  width:1px;height:1px;
  overflow:hidden;
  clip:rect(0 0 0 0);
  white-space:nowrap;
}


/* ---------- no sub-header on the marketing site ----------

   The STRENGTH & CONDITIONING line comes off. The page underneath already says
   what the business does, in a headline and then a paragraph, so a tracked
   caption under the wordmark is the third time in one screen. It also puts the
   mark and the wordmark on one line, which quietens the strip and leaves the
   mark as the only red thing in it besides the button that earns money.

   Hidden, not deleted from the markup, so this stays a CSS-only change and the
   words are still in the DOM for a crawler.

   This rule is the marketing site's alone. The portal surfaces keep their
   sub-header, in gold, naming which hub you are on, and the athlete hub's is
   deliberately 10px and bold. That is the app lane's file and their call. */
.topbar .logo small{display:none}

/* A link in prose is marked with a hairline, not with a colour. The guide links
   inside the CTA strip carry an inline color:var(--bone) inside a var(--bone)
   paragraph, with the reset suppressing the underline, so they read as plain
   text: nine of them across the six calculators and the same shape here.

   This is the third time this exact bug has been found on this site. The backlog
   already records "How that works" shipping as an <a> that inherited its
   paragraph's colour with the underline off, and the smoke sweep passes all of
   them, because legible text that is not identifiably a link is still legible
   text. Matching .src-note a and .refs a, which have always been right. */
.cta-strip p a{border-bottom:1px solid var(--line-red)}
.cta-strip p a:hover{color:var(--red-hot); border-bottom-color:var(--red-hot)}

/* ---------- nav and footer link colour ----------

   Gold already means free everywhere else on this site: the hero freebox, the
   tool pages, the free-to-use tag. A gold nav link is the same promise in the
   same colour, and red-hot stays the brand's own writing.

   Matched on destination rather than on position, so the colour follows the link
   if the order changes again. Measured before writing: --gold on the topbar
   ground is 8.08:1 and --red-hot is 5.12:1, both clear of AA for this size.

   Free Tools is two words and wraps in the 68px strip once the row gets tight,
   which pushes the header taller than the buttons beside it. Nothing in this nav
   should wrap: below 640px the links are hidden anyway and the sticky enquire
   bar takes over. */
.nav-r a.link{white-space:nowrap}
.nav-r a.link[href*="tools"]{color:var(--gold)}
.nav-r a.link[href*="tools"]:hover{color:#E0BC4A}
.nav-r a.link[href*="guides"]{color:var(--red-hot)}
.nav-r a.link[href*="guides"]:hover{color:#F0685A}

/* footer .discs holds Free tools, Guides and Questions and takes its colour from
   the container, so setting the container is enough. All three of those are free
   to use, so all three are gold. */
footer .discs{color:var(--gold)}
footer .discs a:hover{color:#E0BC4A}

/* ===========================================================================
   site.css — website patch. APPEND TO THE END of /site.css.

   Two halves:
     Part 1, the four rules behind the approved design changes.
     Part 2, the code-only fixes (buckets A and B).

   There are also three DELETIONS, which cannot be done by appending — they are
   in site-delete.md, with line references.

   Bump site.css?vN in every page that links it, and dq-shell-vN in sw.js.
   =========================================================================== */

/* ======================= PART 1 — approved design changes ================== */

/* D1. The tier action button. Sits in the slot .tier .foot-note{margin-top:auto}
   already reserves, so all three line up along the bottom of the cards whatever
   the list lengths are. */
.tier .tier-cta{margin-top:auto; width:100%; text-align:center; padding:14px 18px}
/* margin-top:auto ALONE does not align them, which the patch above assumed and
   a browser disproved: measured on desktop the three buttons sat at 5196, 5340
   and 5505, over 300px apart. .tier is a flex column, so auto does push the
   button to the bottom of ITS OWN card, but .tiers carries align-items:start,
   so each card is only as tall as its own content and "the bottom of the card"
   is a different place in each one.
   Equal-height cards are what the change was signed off as: "three tier
   buttons, aligned along the bottom of the cards". Overridden here rather than
   edited at line 360, so this patch's effect is one contiguous block and can be
   lifted back out in one piece. Below 900px the grid is one column and they
   stack, where alignment means nothing either way. */
@media(min-width:900px){ .tiers{align-items:stretch} }

/* D2. The discipline cards were squashed: .dcard .dmore has margin-top:auto,
   which only opens up on the SHORTER cards, so the tallest card in the row had
   its description sitting on the label. A floor under the gap fixes it at every
   height without disturbing the auto. */
.dcard p{margin-bottom:26px}

/* D3. Testimonials, holding. One row at the foot of the coach section, which is
   deliberately the slot real testimonials will occupy — proof between the
   authority and the price. When quotes land they expand in place and nothing
   else on the page moves. A row and not a section, because a section with no
   content in it is filler. */
.soon-band{display:flex; align-items:center; gap:16px; min-height:44px; margin-top:34px;
  padding-top:24px; border-top:1px solid var(--line); transition:.18s}
.soon-band b{font-family:'Oswald'; font-weight:600; text-transform:uppercase;
  letter-spacing:.04em; font-size:17px; color:var(--bone); line-height:1; flex:none}
.soon-band .hr{flex:1; height:1px; background:linear-gradient(90deg,rgba(201,162,39,.35),transparent)}
.soon-band .st{font-family:'JetBrains Mono'; font-size:10px; letter-spacing:.18em;
  text-transform:uppercase; color:var(--gold); flex:none}
.soon-band:hover b{color:var(--gold)}

/* D4. .cta-strip needs no new CSS. The rule has been in this file since the
   tools pass with nothing to match; the patch adds the element it was written
   for. See index-changes.md. */

/* ======================= PART 2 — code-only fixes ========================= */

/* A6. The skip link landed under the sticky bar.
   section,header{scroll-margin-top:84px} is set further up this file, but the
   skip target is <span id="main"> INSIDE a section, so the span itself got no
   margin and the heading arrived beneath the 68px topbar. */
#main{scroll-margin-top:84px}

/* A8. The hero headline vanished in forced-colors mode.
   .hero h1 .stroke (line 102) is color:transparent plus a -webkit-text-stroke.
   Windows high-contrast drops the stroke and keeps the transparent fill, so the
   second line of the biggest text on the site rendered as nothing. */
@media (forced-colors:active){
  .hero h1 .stroke{color:CanvasText; -webkit-text-stroke:0}
}

/* A15. The two hero doors sat 26px apart instead of 14.
   .freebox (line 113) carries margin-bottom:12px from when the boxes were
   stacked by flow. The parent is now a flex/grid with its own gap, so the two
   were adding up. Zeroed only where it has a gap-bearing parent, so the rule
   above is left alone for any page still stacking them. */
.hero-right .freebox{margin-bottom:0}

/* B5. THE ACCESSIBILITY BUG. Below 1100px .cred-cols becomes an
   overflow-x:auto rail (line 188). It has no tabindex and contains no focusable
   element, so credentials 2, 3 and 4 could not be reached by keyboard at all —
   not scrolled, not read. Same shape on .shot-rail (line 356).

   The fix is tabindex="0" + role="group" in the markup (index-changes.md); this
   is the CSS half: the rails are now focus targets, so they need a visible ring,
   and it goes inside the border rather than around it because both rails run to
   the edge of the viewport at narrow widths. */
.cred-cols:focus-visible,.shot-rail:focus-visible{
  outline:2px solid var(--bone); outline-offset:-2px;
}

/* B7. Form success was silent for a screen reader, and failure was a browser
   alert(). #enqOk gets role="status" and focus in the markup; this makes the
   focused panel show a ring, and adds the failure variant of the panel. */
.enq-ok:focus-visible{outline:2px solid var(--bone); outline-offset:3px}
.enq-ok.bad{border-color:rgba(232,131,111,.55)}
.enq-ok.bad b{color:var(--bad)}

/* ===== E1. The two claims that are not features =====

   DQ's call, 21 August 2026, after a pass over what competitors publish. Six
   things this business already does that the market does not, and none of them
   were on the page as anything other than an ordinary bullet.

   TWO PIECES, and they are deliberately the smallest version that works.

   ONE LINE above the tiers, and three MARKED BULLETS inside them. No new
   section, no extra page height on a phone beyond the line itself. The bigger
   treatments were mocked up and rejected: a four-column band above the pricing
   said more and cost roughly half a phone screen, and a boxed panel inside each
   card was louder and added height to all three.

   GOLD, NOT RED, and the reason is in tokens.css: gold already means "free, or
   a caution that is not a fault", and red is the brand and the buy action. A
   third meaning on red would blur the buttons a reader is trying to find. Gold
   is already the colour of `.tier .from`, so this reads as the same family
   rather than a new signal.

   THREE MARKS IS THE CEILING and it is a real constraint rather than a style
   note. Mark six lines and the marking stops meaning anything, which is the
   failure mode of every "featured" badge on every pricing page. If a fourth
   claim earns a mark, one of the three has to lose it. */

.coachline{margin:22px 0 4px}
.coachline p.cl-h{
  font-family:'Oswald'; font-weight:600; text-transform:uppercase; letter-spacing:.02em;
  font-size:clamp(20px,3.4vw,29px); line-height:1.22; color:var(--bone);
  margin:0 0 10px; max-width:22ch; text-wrap:balance;
}
.coachline p.cl-h em{font-style:normal; color:var(--gold)}

/* The marked bullet. `.tier li` already sets the red diamond, so this only
   changes what needs changing: the diamond goes gold and the text comes up to
   --bone from the muted grey.

   `.mk`, the mono "ONLY HERE" label that used to sit above the line, was
   dropped from the markup on 22 August on DQ's instruction: the gold diamond
   already stands out, so the label was saying twice what the colour says
   once. Its rule stayed behind and deadrules caught it, the tool doing
   exactly the job it was built for on the same evening it was hardened. */
.tier li.only{color:var(--bone)}
.tier li.only::before{background:var(--gold); width:8px; height:8px; top:12px}

/* NAV: A LINK THAT ADMITS IT LEADS NOWHERE YET. DQ, 26 August 2026: the
   Athletes tab becomes Coaches, "marked Coming Soon".

   WHY IT IS MARKED IN THE NAV RATHER THAN ONLY ON THE PAGE. /testimonials is
   empty, noindex and out of the sitemap on purpose, because there is no coach
   testimonial yet and inventing one is the thing this codebase refuses to do.
   An unmarked nav link to an empty page spends a reader's click and their
   trust; a marked one is an honest promise. Same reasoning as the soon-band on
   the home page, which this matches deliberately rather than by coincidence.

   The marker inherits the link's own hidden state below 640px, so it cannot
   leave a stray word floating in a nav that is no longer there. */
.nav-r a.link.nav-soon{display:inline-flex; align-items:center; gap:6px}
.nav-r a.link.nav-soon span{font-family:'JetBrains Mono',monospace; font-size:8.5px;
  letter-spacing:.16em; text-transform:uppercase; color:var(--gold);
  border:1px solid rgba(201,162,39,.4); border-radius:3px; padding:2px 4px; line-height:1}
.nav-r a.link.nav-soon:hover span{border-color:var(--gold)}
@media(max-width:640px){.nav-r a.link.nav-soon{display:none}}

/* TIER 3'S LAST THREE, IN BOLD AND GOLD. DQ, 26 August 2026: "tier 1 having 3
   points, tier 2 having 6 points, and tier 3 having 9 points. The
   differentiators need to be called out in bold and gold. I.e., no bold or
   gold in tier 1 and tier 2."

   THIS REVERSES WHAT WAS LIVE rather than adding to it. Tier 2's final two
   bullets carried .only and were bold. His instruction is explicit that tiers
   1 and 2 carry no emphasis at all, so .only is now tier 3's alone. Written
   down because a later reader will find bold markup removed from a tier and
   reasonably assume it was lost in a merge. */
.tier ul li.only{color:var(--gold); font-weight:600}

/* ABOUT ME's prose column. .lineage-col is display:flex because it used to hold
   a single .lineage rail and stretch it to the portrait's height. Dropping
   paragraphs straight into it made each <p> a flex CHILD, so three paragraphs
   became three 90px columns of text beside the photo: the same ragged, too-thin
   look DQ called "disjointed" on the four cards below it, produced a second way
   on the same page. Wrapped rather than changing .lineage-col, because that rule
   still has the rail to lay out. Same red hairline as the rail so the two read
   as one design rather than two. */
.about-prose{border-left:1px solid var(--line-red-soft); padding-left:22px;
  display:flex; flex-direction:column; gap:16px; justify-content:center}
.about-prose .lead{margin:0; max-width:62ch}
@media(max-width:860px){.about-prose{justify-content:flex-start}}

/* THE DESKTOP SLOT IN A RAIL BUILT FOR PHONES. The Coach Hub runs on a laptop,
   so its main shot is 1440x1000 while every athlete-app shot is 780x1600.
   Dropping the wide one into the phone frame crops it to 33.9% of its width
   under object-fit:cover, measured rather than guessed, which throws away most
   of the roster on the one screen whose whole argument is that it shows the
   whole roster.

   object-fit:contain rather than cover, and object-position centred: a
   dashboard cropped is a dashboard misrepresented, where an app screen cropped
   at the bottom still reads correctly, which is why the phone shots use cover
   and this does not. The 12px inset keeps the ground visible around it so it
   reads as a screen inside a device rather than a picture that failed to fill
   its box. */
/* WIDTH DERIVED SO BOTH FRAMES ARE THE SAME HEIGHT, rather than picked. A phone
   card is 250px wide at 780/1600, so its frame is 250*1600/780 tall; a 1440/1000
   frame of that height is 250*1600/780*1440/1000 wide. Hardcoding 520px looked
   fine and put the two captions 150px apart vertically, which reads as a
   layout fault rather than as two different devices. Derived, they share a
   baseline and the pair fills the rail instead of leaving a third of it empty.

   The phone override is deliberately NOT derived: at 390px the same arithmetic
   gives a 620px card, and a card wider than the screen is worse than two
   captions that do not line up in a view you are scrolling vertically anyway. */
.shot.shot-wide{width:calc(250px * 1600 / 780 * 1440 / 1000)}
.shot.shot-wide .frame{aspect-ratio:1440/1000; border-radius:14px; padding:12px}
.shot.shot-wide img{object-fit:contain; object-position:center; border-radius:6px}
@media(max-width:640px){ .shot.shot-wide{width:320px} }
