/*
 * The public site's section vocabulary.
 *
 * Every marketing page is built from the components in this file: the vertical
 * rhythm, the section head with its rule-and-label, the card grids and the
 * subgrid alignment that squares them off, the buttons, the tables, the FAQ,
 * and the empty slots that stand in for art.
 *
 *
 * WHY IT IS A FILE AND NOT MORE INLINE CSS
 *
 * It was 365 lines inside public/landing.html, and the nine feature and
 * audience pages each had their own partial re-statement of the same ideas -
 * 365 distinct rule lines between them, 120 of which appeared on more than one
 * page, and the three audience pages carrying 128 lines of byte-identical CSS
 * three times over. That is how nine pages ended up with six different heading
 * sizes, none of which anybody chose.
 *
 * Being a real file rather than an injected <style> also means it is fetched
 * once and cached for the next eight pages; inline CSS is re-sent with every
 * document.
 *
 *
 * HOW IT WINS
 *
 * publicChrome.js links it immediately before </head>, which puts it after each
 * page's own <style> and before the chrome's. So it beats a page's local copy
 * of a component at equal specificity, and the chrome still beats it for the
 * nav and the footer, which are the chrome's to decide.
 *
 * The colours are all tokens from views/publicTokens.js. There are no hex
 * values in here on purpose - the one exception is the arrow head in the step
 * connector, which is a data URI and cannot read a custom property.
 *
 *
 * The section designs are ported from UIdeck's "Play" template (MIT, no
 * attribution required) - its rhythm, its section-title block, its feature card
 * with the rotated ghost behind the icon, its alternating text-beside-panel
 * band. Bootstrap is not ported: Play is built on the Bootstrap grid and ~200KB
 * of framework CSS, and this site shares one stylesheet across 27 pages.
 */

*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth}
body{font-family:var(--sans);background:var(--paper);color:var(--ink);line-height:1.6;-webkit-font-smoothing:antialiased}
::selection{background:var(--accent);color:var(--accent-ink)}
a{color:inherit;text-decoration:none}
img{max-width:100%}
.ti-svg{width:1em;height:1em;display:inline-block;vertical-align:-0.125em;flex-shrink:0}

/* ---------- section rhythm ----------
   Play uses 120px top / 90px bottom, tightening to 80/40 on a phone. Kept,
   because a consistent vertical beat is most of why a long page reads as one
   document rather than a pile of slides. */
.sec{padding:112px 0 96px}
.sec-tint{background:var(--tint-fade)}
/* A document or a form does not need the full 112px lead-in: the page head
   above it is already a large block of space. */
.sec-tight{padding-top:62px}
.sec-flush{padding-bottom:0}
@media(max-width:700px){.sec{padding:74px 0 60px}}

.sec-head{max-width:640px;margin-bottom:58px}
.sec-head.mid{margin-left:auto;margin-right:auto;text-align:center}
/*
 * The section label, with a rule beside it.
 *
 * The label is --accent-readable, which is the brightest orange that still
 * carries 13px text; the rule is --accent at full strength, because a line is
 * decoration and has no contrast floor to clear. So the bright orange is in
 * the section head after all, just not in the part that has to be read.
 *
 * One rule, on the left, matching the reference site - a trailing line beside
 * left-aligned text points at nothing. Centred heads get one on each side.
 */
.kicker{display:flex;align-items:center;gap:11px;font-size:13px;font-weight:600;letter-spacing:.09em;text-transform:uppercase;color:var(--accent-readable);margin-bottom:14px}
.kicker::before{content:"";width:26px;height:2px;background:var(--accent);flex:0 0 26px;border-radius:2px}
/* The hero's label is centred too, and its kicker is not inside a .sec-head -
   it sits directly in the hero - so it needs naming here as well. */
.sec-head.mid .kicker,.top-hero .kicker{justify-content:center}
.sec-head.mid .kicker::after,.top-hero .kicker::after{content:"";width:26px;height:2px;background:var(--accent);flex:0 0 26px;border-radius:2px}
/* Any h2 in any section, not just one inside a .sec-head - see the note in
   the commit that moved features.html across. */
.sec h2{font-family:var(--display);font-weight:600;font-size:clamp(27px,3.3vw,40px);line-height:1.18;letter-spacing:-.02em;color:var(--ink);margin-bottom:16px}
.sec-head p{font-size:18px;line-height:1.65;color:var(--muted)}
@media(max-width:700px){.sec-head p{font-size:16px}.sec-head{margin-bottom:40px}}

/* ---------- buttons ---------- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:9px;padding:14px 26px;border-radius:9px;font-size:15px;font-weight:600;font-family:var(--sans);border:1px solid transparent;cursor:pointer;transition:background .2s,border-color .2s,transform .15s,box-shadow .2s}
.btn:hover{transform:translateY(-1px)}
/*
 * Black, not orange, and the same hierarchy as the header and the closing
 * panel: the primary action reads as black-on-white everywhere on the site,
 * so the three places that ask for a demo ask in one voice. White on
 * near-black is 18.2:1, the strongest pair available here.
 */
.btn-primary{background:var(--ink);color:var(--white);border-color:var(--ink)}
.btn-primary:hover{background:var(--ink-soft)}
/*
 * The secondary was white with a grey border, which on a white page is a
 * button you have to look for. It takes the pale orange instead - the same
 * fill the app's report links use - so it has an edge of its own without
 * competing with the black. Near-black on it is 16:1.
 */
.btn-ghost{background:var(--accent-wash);color:var(--ink);border-color:rgba(224,99,58,.28);box-shadow:none}
.btn-ghost:hover{background:var(--accent-wash);border-color:rgba(224,99,58,.5)}
/*
 * Solid orange, and a THIRD button rather than a change to the ghost.
 *
 * The hero wants its second action to carry as much weight as the first; every
 * other secondary button on the site still wants to sit behind the black one.
 * Recolouring .btn-ghost would have moved all 30-odd of them at once to make
 * one of them louder, so this is opt-in and the ghost is untouched.
 *
 * --accent-readable rather than --accent, and not for tidiness: this button
 * carries white words. White on --accent is 3.49:1 and fails; on this it is
 * 5.27:1. It is also exactly the nav's Login button, which is what "the same
 * shade as the login" asks for - and the hero's own highlighted word already
 * uses it, so the three oranges above the fold are one colour.
 */
.btn-accent{background:var(--accent-readable);color:var(--white);border-color:var(--accent-readable)}
.btn-accent:hover{background:#96351b;border-color:#96351b}

/* ---------- the empty visual slots ----------
   Deliberately unfinished and deliberately obvious. Every one states what
   belongs in it and at what proportion, so the page can be judged on its
   layout now and the art can be dropped in later without the boxes moving. */
.ph{border:1.5px dashed rgba(17,22,29,.2);border-radius:14px;background:repeating-linear-gradient(45deg,rgba(17,22,29,.022) 0 11px,transparent 11px 22px);display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:26px;color:var(--muted);font-size:13px;line-height:1.5}
.ph b{display:block;font-size:13px;font-weight:600;color:var(--ink);margin-bottom:5px;letter-spacing:.01em}
.ph-wide{aspect-ratio:16/10;width:100%}

/* The four step pictures. No frame - these sat in a bordered card for one
   revision and the border is deliberately gone, so the art meets the page
   directly and each picture's own white ground is what surrounds it.

   5:4, because that is the shape the four FILES are. The four illustrations
   are natively 1.00, 1.10, 1.16 and 1.32 to one, so in any single box they
   rendered at four different heights and the row looked ragged. They are
   rebuilt onto one identical 800x640 canvas instead, each trimmed of its own
   white border and then scaled to a shared artwork height of 606 - 606 being
   the tallest the WIDEST of them can be before it overflows 800 wide. The
   evening-up is done in the files, where it is a one-time cost, rather than in
   CSS, which cannot make four different shapes equal without cropping them.

   contain rather than cover is now belt and braces: the files match this ratio
   exactly, so neither crops nor letterboxes anything. It is here so that an
   image swapped in later at some other shape shrinks to fit instead of being
   cut - cover would take a quarter of the height off a square one, which is
   where the standing figures' heads and feet are.

   height:auto is load-bearing, not tidiness. width and height on an <img> are
   presentational hints - real CSS width and height at the bottom of the
   cascade. width:100% overrides the width hint, but with no height declared
   the height hint SURVIVES, and an explicit height beats aspect-ratio. Without
   this line every frame takes its natural pixel height - 800px tall boxes,
   staggered, each with a small picture adrift in the middle of it. */
.step-visual{display:block;width:100%;height:auto;aspect-ratio:5/4;object-fit:contain}

/* The hero art replaces the 16:8.4 placeholder that used to sit here, and is
   3:2 rather than that letterbox - cropping it to the old shape would have cut
   the clock, the graduation cap and the code tag off the top and bottom, which
   are the details that make it read as assessment rather than as a person at a
   desk. So the slot takes the picture's shape instead of the reverse.

   No background treatment, and none needed: --tint-fade reaches solid --paper
   by 50% down the hero and the art sits well below that, so the illustration's
   own white ground meets white. Height is left to the aspect ratio rather than
   fixed, but width and height ARE on the tag - without them the page reflows
   when the image lands, which is the layout shift Search Console counts. */
.hero-visual{display:block;width:100%;max-width:900px;height:auto;margin:46px auto 0}
@media(max-width:700px){.hero-visual{margin-top:32px}}

/* ---------- hero ----------
   On the header wash, and continuous with it: the nav is the same colour and
   is no longer an overlay, so the top of the page is one soft orange block
   that ends at the hero's lower edge. The old hero was near-black, which is a
   hard thing to put at the top of a page whose whole argument is white. */
/* The hero opens the page the way every other section opens: the tint at the
   top edge, faded out before the words. It sits under the floating pill, so
   the orange starts behind the header rather than at the headline - which is
   what makes the pill look like it belongs to the page instead of sitting on
   top of it. */
.top-hero{background:var(--tint-fade);margin-top:-104px;padding:168px 0 88px;text-align:center}
@media(max-width:760px){.hero{margin-top:-84px;padding:132px 0 64px}}
.top-hero h1{font-family:var(--display);font-weight:600;font-size:clamp(33px,4.5vw,55px);line-height:1.08;letter-spacing:-.025em;max-width:15.5em;margin:0 auto 22px}
.top-hero h1 em{font-style:normal;color:var(--accent-readable)}
/* --muted, not --on-accent. The latter is a dark brown built to sit on an
   orange fill; on white it reads as a mistake rather than as secondary text. */
.top-hero .lede{font-size:19px;line-height:1.62;color:var(--muted);max-width:33em;margin:0 auto 34px}
/* The hero copy column. Eight pages wrap their hero text in this, so it is
   part of the shared hero rather than something each of them re-declares.
   The h1 and the lede set their own measures inside it. */
.hero-copy{max-width:850px;margin:0 auto}
/* Two-column heroes: the copy sits left with its own measure, and the h1 stops
   centring itself inside a column it does not own. */
.top-hero.hero-split{text-align:left}
.top-hero.hero-split h1{margin-left:0;margin-right:0;max-width:none}
.top-hero.hero-split .lede{margin-left:0;margin-right:0}
.top-hero.hero-split .hero-cta{justify-content:flex-start}
.top-hero.hero-split .kicker{justify-content:flex-start}
.top-hero.hero-split .kicker::after{display:none}
.top-hero.hero-split .hero-copy{margin:0}
.hero-cta{display:flex;gap:13px;align-items:center;justify-content:center;flex-wrap:wrap}
@media(max-width:700px){
  .top-hero{padding:56px 0 64px}
  .top-hero .lede{font-size:16.5px}
  .hero-cta{flex-direction:column;align-items:stretch}
}

/* ---------- card grids ---------- */
/*
 * The card grids, and the reason they are grids rather than flex rows.
 *
 * A card whose title wraps to two lines pushes everything under it down, so
 * across a row of three the descriptions started at three different heights
 * and the links finished at three different heights. Each card was correct
 * and the row was ragged.
 *
 * subgrid fixes it at the root: the row owns the tracks - icon, title,
 * description, link - and every card in it inherits them, so each band is as
 * tall as the tallest card needs and all four line up regardless of how the
 * text wraps. No min-heights to guess at and nothing to re-tune when the copy
 * changes.
 *
 * Where subgrid is missing the cards fall back to a column with the link
 * pushed to the bottom, which still squares off the top and bottom edges and
 * leaves only the middle ragged - the behaviour we had, not worse than it.
 */
.grid3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:46px 40px}
.grid4{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:34px 28px}
.grid3 > *,.grid4 > *{display:flex;flex-direction:column}
.grid3 > * > :last-child,.grid4 > * > :last-child{margin-top:auto}
@media(max-width:940px){.grid3,.grid4{grid-template-columns:repeat(2,minmax(0,1fr));gap:36px 26px}}
@media(max-width:620px){.grid3,.grid4{grid-template-columns:1fr}}

/* Play's feature card: a rounded icon tile with a second copy of itself
   rotated behind at 20% opacity, which straightens slightly on hover. It is
   one of the few purely decorative things on this page and it costs nothing,
   because it is the same element drawn twice. */
.feat-icon{width:60px;height:60px;border-radius:14px;background:var(--accent);color:var(--accent-ink);display:flex;align-items:center;justify-content:center;font-size:25px;position:relative;z-index:1;margin-bottom:26px}
.feat-icon::before{content:"";position:absolute;inset:0;border-radius:14px;background:var(--accent);opacity:.2;z-index:-1;transform:rotate(23deg);transition:transform .3s}
.feat:hover .feat-icon::before{transform:rotate(45deg)}
/*
 * A floor of four lines under the paragraphs that have something aligned
 * beneath them.
 *
 * Evening the copy so every card wraps to the same depth works at the width
 * it was written for and stops working at the next breakpoint, because the
 * column gets wider and one card drops to three lines while its neighbours
 * stay at four. Reserving the lines makes the band the same height whatever
 * the wrap does, so the gap under the text is the same in every card at every
 * width. 1.62 line-height x 4.
 *
 * .feat and .who are NOT in this list any more, and the reason is that their
 * copy got shorter than the floor. Four reserved lines under two or three
 * lines of text is dead space, which read as a 2.9-line hole under a .feat
 * paragraph and a 2.0-line one under a .who paragraph - measured, not guessed.
 * A floor only costs nothing while the copy actually reaches it.
 *
 * What replaces it for both is the subgrid block at the foot of this file: the
 * card-body sits in its own track, sized to the tallest body in the band, so
 * the links and the tick lists still line up across a row without any line
 * being reserved in advance. The floor stays on .step, whose paragraphs are
 * three to five lines and do reach it, and which needs its band held steady
 * because what sits under it is a picture rather than a line of text.
 */
.step p{min-height:6.48em}

.feat h3{font-size:19px;font-weight:600;line-height:1.35;color:var(--ink);margin-bottom:10px}
/* 24px is one line of this paragraph (15px x 1.62), so the link sits exactly
   one line under the last line of text rather than at the 15px that was tuned
   against a four-line floor. */
.feat p{font-size:15px;line-height:1.62;color:var(--muted);margin-bottom:24px}
.feat-link{font-size:14px;font-weight:600;color:var(--accent-readable);display:inline-flex;align-items:center;gap:6px}
.feat-link:hover{gap:10px}
.feat-link .ti-svg{transition:transform .2s}

/* Problem cards - flatter than the capability cards on purpose. These state
   a difficulty; the capability cards offer something, and the page should not
   give both the same weight. */
.prob{background:var(--white);border:1px solid var(--line-dark);border-radius:14px;padding:30px 28px}
.prob-mark{width:42px;height:42px;border-radius:10px;background:var(--accent-wash);color:var(--accent-readable);display:flex;align-items:center;justify-content:center;font-size:20px;margin-bottom:20px}
.prob h3{font-size:17px;font-weight:600;line-height:1.35;margin-bottom:9px;color:var(--ink)}
.prob p{font-size:14.5px;line-height:1.62;color:var(--muted)}

/* How many bands each row of cards has, so subgrid knows how many tracks to
   hand out. Set per section because the card shapes genuinely differ - a
   problem card is mark/title/text, a step adds a visual, a use case adds a
   list and a button. */
/* How many bands a card is built from, said on the grid rather than keyed
   to a section id, so the same grid works on any page.
   The heading and its paragraph count as ONE band - see .card-body in the
   subgrid block at the foot of this file. */
.rows-2{--rows:2}
.rows-3{--rows:3}
.rows-4{--rows:4}
.rows-5{--rows:5}
.card-body{min-width:0}

/* ---------- how it works ---------- */
.step{position:relative}
/*
 * The connector, and it runs the whole way between one number and the next
 * rather than sitting as a chevron in the gap. A short mark in the middle of
 * a wide gap reads as punctuation; a line that reaches from this circle to
 * that one reads as a sequence, which is the only reason the arrows are here.
 *
 * Two backgrounds on one pseudo-element: a stretched 1.5px rule for the
 * shaft, and a fixed-width SVG head pinned to its right end. The shaft is a
 * gradient rather than a border so it can be sized to "all of it but the
 * eight pixels the head needs".
 *
 * The head is a data URI, so its colour is written out rather than taken from
 * a token - the one place on this page where a hex value is unavoidable.
 *
 * Decoration: the numbers already carry the order, so this never reaches the
 * accessibility tree. Hidden below 940px where the row wraps and an arrow off
 * the right edge would point at nothing.
 */
.step:not(:last-child)::after{content:"";position:absolute;top:12px;left:46px;right:-16px;height:10px;pointer-events:none;background:linear-gradient(var(--accent),var(--accent)) left center/calc(100% - 9px) 1.5px no-repeat,url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='9' height='10' viewBox='0 0 9 10'%3E%3Cpath d='M1 1.2 5.8 5 1 8.8' fill='none' stroke='%23e0633a' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") right center/9px 10px no-repeat}
@media(max-width:940px){.step:not(:last-child)::after{display:none}}
/* Orange with black on it, 5.20:1 - the same arrangement as every other
   orange fill on the site. It was near-black, which made the sequence read as
   four bullets rather than as a path through the product. */
.step-n{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:50%;background:var(--accent);color:var(--accent-ink);font-size:14px;font-weight:700;margin-bottom:18px}
/* A line of air before the visual, so the picture is not read as part of the
   paragraph that ends just above it. 44px here read as a gap rather than as a
   break, because the art carried its own blank edge on top of it. */
.step-visual{margin-top:22px}
.step h3{font-size:17px;font-weight:600;line-height:1.35;margin-bottom:9px;color:var(--ink)}
.step p{font-size:14.5px;line-height:1.62;color:var(--muted)}

/* ---------- the four deep dives ----------
   Play's "about" band: a white bordered panel on a tinted ground, text one
   side and art the other, alternating down the page. */
/* Four rows of ONE white block, not four cards.

   No outline and no divider between the halves: both halves are white, so the
   line between them was drawing a join that is not there. No gap between the
   rows either - the 26px of tint that used to show through read as four
   separate cards, and the point of this section is one slab with the picture
   alternating side to side down it.

   Which means the radius cannot stay on every row, or the corners notch at
   every join and the tint shows through in eight little wedges. It belongs to
   the BLOCK: the top two corners on the first row, the bottom two on the last.
   first-of-type and last-of-type rather than first-child, because .sec-head is
   a sibling and is not an article. */
.usp{display:grid;grid-template-columns:1fr 1fr;background:var(--white);overflow:hidden}
.usp:first-of-type{border-radius:16px 16px 0 0}
.usp:last-of-type{border-radius:0 0 16px 16px}
.usp-body{padding:54px 50px;align-self:center}
/* --ink, not the orange: this tag sits on --accent-wash, where the readable
   orange is 4.44:1. The panel is orange already. */
.usp-tag{display:inline-block;font-size:12px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;background:var(--accent-wash);color:var(--ink);padding:6px 14px;border-radius:999px;margin-bottom:18px}
.usp h3{font-family:var(--display);font-weight:600;font-size:clamp(22px,2.3vw,28px);line-height:1.24;letter-spacing:-.015em;color:var(--ink);margin-bottom:14px}
.usp p{font-size:15.5px;line-height:1.68;color:var(--muted);margin-bottom:22px}
.usp-visual{background:var(--white);position:relative;padding:28px}
.usp-visual .ph{width:100%;aspect-ratio:4/3}
/* The deep-dive art. This panel is WHITE rather than tinted, and that one
   choice is what makes the rest of it simple.

   The panel has no fixed shape - its width is half the card but its height
   comes from the text beside it, so the ratio moves with the viewport and with
   how many lines each paragraph wraps to; measured at 1.08, 1.15 and 1.25
   between 820 and 1920 wide. A picture in a box of changing shape either
   letterboxes or crops, and there is no third option.

   Both were bad while the panel was tinted: letterboxing showed a peach margin
   around the art, and these four illustrations have almost NO slack of their
   own to crop into - the isometric one measures 0% inset on all four sides, so
   cropping takes platform, not background.

   On white it stops being a choice at all. These were drawn on white, so their
   own pale circles and blobs are already meant to sit on it, and the files are
   trimmed to the artwork and squared on a white ground. contain then crops
   nothing, and the space it leaves over is white against a white panel - the
   margin is still there and simply cannot be seen.

   The white also un-bakes a dependency: the earlier version painted the files
   in the panel's tint, so changing --tint would have silently mismatched them.

   absolute, and that is the whole point of it. The files are square, so an
   in-flow image hands the grid row its own height and the CARD grows to match
   the picture - 550px tall at 1920, with the paragraph stranded in the middle
   of its half. Out of flow it contributes no height at all, so the row goes
   back to being measured by the text beside it and the picture fits itself into
   whatever that leaves. The text sets the size of the card; the picture does
   not get a vote. */
.usp-visual .usp-shot{position:absolute;inset:28px;display:block;width:calc(100% - 56px);height:calc(100% - 56px);object-fit:contain}
/* Alternating: the even bands put the art on the left. Done with `order` so
   the markup stays in reading order for a screen reader and for a phone,
   where both columns stack and art-first would bury the sentence. */
.usp.flip .usp-body{order:2}
.usp.flip .usp-visual{order:1}
@media(max-width:860px){
  .usp{grid-template-columns:1fr}
  .usp-body{padding:38px 28px;order:1 !important}
  .usp-visual{order:2 !important;padding:24px 24px 28px}
  /* Stacked, there is no text beside the picture to take the height from, and a
     panel whose only child is absolute would collapse to nothing. So the image
     comes back into flow here and sets its own height from the file's square. */
  .usp-visual .usp-shot{position:static;width:100%;height:auto;aspect-ratio:1/1}
}

/* ---------- use cases ---------- */
.who{background:var(--white);border:1px solid var(--line-dark);border-radius:14px;padding:34px 30px;display:flex;flex-direction:column}
.who-icon{width:46px;height:46px;border-radius:11px;background:var(--ink);color:var(--white);display:flex;align-items:center;justify-content:center;font-size:21px;margin-bottom:22px}
.who h3{font-size:19px;font-weight:600;margin-bottom:9px;color:var(--ink)}
/* 24px is one line of this paragraph, the same deliberate single line of air
   the .feat cards put under theirs. It was 20px, tuned against the four-line
   floor this no longer carries. */
.who p{font-size:15px;line-height:1.62;color:var(--muted);margin-bottom:24px}
.who ul{list-style:none;margin:0 0 22px;padding:0;display:flex;flex-direction:column;gap:9px}
.who li{font-size:14.5px;line-height:1.5;color:var(--slate);display:flex;gap:9px;align-items:flex-start}
.who li .ti-svg{color:var(--accent-readable);margin-top:4px;flex-shrink:0}
.who-foot{margin-top:auto}

/* ---------- compare ---------- */
/*
 * The container scrolls only where the table cannot fit.
 *
 * overflow-x:auto makes overflow-y compute to auto as well, and an auto box
 * CLIPS anything absolutely positioned inside it - which would swallow the
 * whole info bubble, since the button that opens it lives in a table header.
 * The table's min-width is 860px, and .wrap hands it exactly that at a 960px
 * viewport - measured, because the arithmetic is the page padding plus the
 * scrollbar and guessing it put the breakpoint 20px too low, where the table
 * outgrew its own container while still fitting the page. Above 960 there is
 * nothing to scroll and the box stays visible so the bubble can leave it.
 */
.cmp-scroll{background:var(--paper);border:1px solid var(--line-dark);border-radius:14px}
@media(max-width:960px){.cmp-scroll{overflow-x:auto}}
/*
 * separate rather than collapse, and that is what buys the rounded corners.
 *
 * border-collapse:collapse merges each cell's edges into a shared grid and
 * border-radius stops applying - so a rounded container would have the table's
 * square corners sitting on top of it. The obvious fix, overflow:hidden on the
 * container, cannot be used here: it would clip the info bubble. So the four
 * corner CELLS carry the radius themselves and the container never clips.
 */
table.cmp{width:100%;border-collapse:separate;border-spacing:0;min-width:860px;background:var(--paper)}
/* Rows separate, columns do not. A full grid reads as a spreadsheet; a
   horizontal rule per row is the softer frame the rest of the page uses. */
table.cmp th,table.cmp td{padding:16px 18px;font-size:14.5px;border-bottom:1px solid var(--line-dark);vertical-align:middle;text-align:center}
table.cmp thead th:first-child{border-top-left-radius:13px}
table.cmp thead th:last-child{border-top-right-radius:13px}
table.cmp tbody tr:last-child td:first-child{border-bottom-left-radius:13px}
table.cmp tbody tr:last-child td:last-child{border-bottom-right-radius:13px}
/* The row label reads as a sentence and stays left. The three value columns
   hold one or two words each and are centred under their headings, so the
   eye can run down a column and compare rather than scanning for where each
   answer starts. */
/*
 * Two steps down from the solid --accent the table first carried.
 *
 * The header takes --accent-soft and the column below it --accent-wash, which
 * is the normal direction for a table - the heading is the strongest thing in
 * its column and everything under it recedes. Both hold --ink comfortably:
 * 9.34:1 on the header, 15.32:1 on the column, against the 5.20:1 the solid
 * orange was managing. Softer here also means MORE readable, not less.
 */
table.cmp thead th{font-size:13px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--ink);background:var(--accent-soft);white-space:nowrap}
/* 22%, down from 34%. The labels were the longest thing in the table when the
   value cells were single words; now they are the shortest, and a third of the
   width spent on them is a third the three columns being compared do not get. */
table.cmp td.row-label{font-weight:600;color:var(--ink);width:22%}
/* The same pale orange as the header row above it, so our column reads as one
   band from the heading to the last row rather than as a lighter patch under
   a darker label. */
table.cmp td.us{background:var(--accent-wash);color:var(--ink)}
/*
 * The "i", lifted from the app's .td-info so the two surfaces explain
 * themselves the same way: a small ring you can hover or tab to, and a black
 * bubble that separates itself from whatever it covers.
 *
 * Two deliberate differences. The app's hover fills the ring with --accent,
 * which would disappear here because the header it sits on is already orange,
 * so this inverts to ink instead. And the resets matter more here: the button
 * inherits uppercase and letter-spacing from the header cell, which would
 * render the i as a spaced-out I.
 */
.cmp-info{
  display:inline-flex;align-items:center;justify-content:center;
  width:13px;height:13px;margin-left:6px;padding:0;
  /* --slate, not --muted. The ring is a UI boundary and needs 3:1 against the
     header it sits on; --muted is 2.95:1 there and --slate is 4.95:1. */
  border:1px solid var(--slate);border-radius:999px;background:transparent;
  color:var(--slate);font:700 8px/1 var(--sans);letter-spacing:0;
  text-transform:none;cursor:help;
  /* inline-flex sits on the text baseline, which drops the ring below the
     centre of the heading's cap height. This lifts it onto the same line. */
  position:relative;vertical-align:middle;top:-1px;
}
.cmp-info:hover,.cmp-info:focus-visible{background:var(--ink);border-color:var(--ink);color:var(--paper)}
.cmp-info-bubble{
  display:none;position:absolute;top:calc(100% + 9px);left:-6px;z-index:400;
  width:max(320px,min(460px,70vw));padding:12px 14px;
  border-radius:9px;background:#000;color:#fff;
  font:400 12.5px/1.65 var(--sans);letter-spacing:0;
  text-align:left;text-transform:none;white-space:normal;font-weight:400;
  box-shadow:0 14px 34px rgba(0,0,0,.32);
}
.cmp-info:hover .cmp-info-bubble,.cmp-info:focus-visible .cmp-info-bubble{display:block}
.cmp-note{margin-top:18px;font-size:13.5px;line-height:1.6;color:var(--muted)}

/* ---------- pricing ----------
   The home page's own plan cards lived here - .tiers3, .tier, .tier-flag,
   .tier-for - and they are gone with that section.

   Removing them is not tidying. This stylesheet is linked by injectPublicChrome
   AFTER views/pricingTiers.js has written its <style> into the same <head>, so
   at equal specificity these rules were WINNING on /pricing, where a different
   .tier is the real product card. `.tier{display:flex}` here was quietly
   cancelling the display:grid that page's subgrid alignment depends on, and
   `.tier h3{font-size:19px}` was cancelling its 26px heading - which is why the
   three plan boxes would not line up no matter what was written over there.

   Two unrelated components sharing a class name across two stylesheets is the
   whole bug. The pricing page's cards are styled in views/pricingTiers.js. */

/* ---------- faq ----------
   <details>, so it opens with no JavaScript at all and its content is in the
   page for a crawler whether or not it is open. */
.faq-list{max-width:820px;margin:0 auto;display:flex;flex-direction:column;gap:13px}
.faq{background:var(--white);border:1px solid var(--line-dark);border-radius:12px;padding:0 24px}
.faq summary{list-style:none;cursor:pointer;padding:21px 0;font-size:16.5px;font-weight:600;color:var(--ink);display:flex;align-items:center;justify-content:space-between;gap:16px}
.faq summary::-webkit-details-marker{display:none}
.faq summary .ti-svg{color:var(--accent-readable);flex-shrink:0;transition:transform .2s}
.faq[open] summary .ti-svg{transform:rotate(180deg)}
.faq p{font-size:15px;line-height:1.7;color:var(--muted);padding:0 0 22px;max-width:62em}

/*
 * This block sits LAST on purpose.
 *
 * `.grid3 > *` and `.who` have the same specificity, so whichever is
 * written later wins - and with the block up beside the grid definitions,
 * `.who{display:flex}` further down the file quietly turned the use-case
 * cards back into flex columns and subgrid never applied to them. Putting
 * it after every card rule is what makes it authoritative for all of them.
 */
@supports (grid-template-rows:subgrid){
  /*
   * row-gap is ZERO here, and that is the whole point of this block.
   *
   * Once the cards are subgrids, the PARENT's row-gap falls between every one
   * of its tracks - including the ones inside a card. The 46px meant as space
   * between one row of cards and the next landed between each heading and its
   * own paragraph as well, so a card that should have had 10px there had 56.
   * The spacing inside a card comes from the elements' own margins, as it did
   * before subgrid; the gap supplies none of it.
   */
  .grid3,.grid4{grid-template-rows:repeat(var(--rows,4),auto);row-gap:0}
  .grid3 > *,.grid4 > *{display:grid;grid-row:span var(--rows,4);grid-template-rows:subgrid;align-content:start}
  /*
   * .card-body is the heading and its paragraph as ONE band, and it is what
   * finally settles this.
   *
   * With them in separate bands, the heading's band was as tall as the
   * tallest heading in the row, so a one-line heading had a spare line to put
   * somewhere. Top-aligned it fell between the heading and its own paragraph.
   * Bottom-aligned it fell above the heading, which moved the problem to the
   * gap after the icon rather than removing it. There is no third place to
   * put it - the fix is not to create the spare line, which means not giving
   * the heading a band of its own.
   *
   * So the icon has the same margin under it in every card, the paragraph
   * follows its own heading at its own 10px, and the row still lines up where
   * it matters: icons across the top, actions across the bottom.
   */
  .grid3 > * > :last-child,.grid4 > * > :last-child{margin-top:0;align-self:end}
  /* Except the step visual, which wants a line of air above it so the picture
     is not read as part of the paragraph. The margin-top:0 above exists only
     to undo the `margin-top:auto` of the non-subgrid fallback, and it was
     quietly winning here on specificity. */
  .grid4 > * > .step-visual{margin-top:22px}
  /* Unless that last element is the body block itself, in which case
     bottom-aligning it lines up the last lines of text and scatters the
     first ones - the opposite of what is wanted. */
  .grid3 > * > .card-body:last-child,.grid4 > * > .card-body:last-child{align-self:start}
  /*
   * And the space between card rows, which row-gap can no longer provide, is
   * a margin on the card. The grid takes the same amount back off its own
   * bottom, so a grid that does not wrap is unchanged and one that wraps gets
   * the gap only where it was wanted.
   */
  .grid3 > *,.grid4 > *{margin-bottom:46px}
  .grid3,.grid4{margin-bottom:-46px}
}

/* ---------- one reveal, and it degrades to "visible" ----------
   Scroll-driven CSS rather than a library. The element is visible by default
   and the animation is layered on top where the browser supports it, so
   nothing on this page depends on a script having run - which is the failure
   mode of every JS reveal: a crawler or a slow phone sees an empty page.
   The old version of this file shipped exactly that, plus a second system
   that pinned each section to the full height of the screen. */
.rise{opacity:1}
@media (prefers-reduced-motion:no-preference){
  @supports (animation-timeline:view()){
    .rise{animation:rise-in linear both;animation-timeline:view();animation-range:entry 0% entry 34%}
    @keyframes rise-in{from{opacity:0;transform:translateY(15px)}to{opacity:1;transform:none}}
  }
}

/* ---------- long-form documents ----------
   The five legal pages: privacy, terms, the DPA, retention and the student
   data notice. Every one of them carried its own copy of this, plus fifty
   lines of nav and footer CSS that the injected chrome had superseded years
   ago and that no markup on the page referenced.

   The section rule between clauses used to be an empty <div class="divider">,
   fifty-nine of them across the five pages. A heading that draws its own rule
   above itself cannot fall out of step with the heading it belongs to, and it
   is one element instead of two. */
.doc{max-width:760px}
.doc h2{font-family:var(--display);font-size:21px;font-weight:600;letter-spacing:-.015em;line-height:1.35;color:var(--ink);margin:42px 0 14px;padding-top:38px;border-top:1px solid var(--line-dark)}
.doc h2:first-child{margin-top:0;padding-top:0;border-top:0}
.doc p{font-size:16px;line-height:1.75;color:var(--muted);margin-bottom:14px}
.doc p:last-child{margin-bottom:0}
.doc ul{list-style:none;display:flex;flex-direction:column;gap:9px;margin:0 0 16px}
.doc li{position:relative;padding-left:22px;font-size:16px;line-height:1.7;color:var(--muted)}
.doc li::before{content:"";position:absolute;left:3px;top:.68em;width:6px;height:6px;border-radius:50%;background:var(--accent-soft)}
.doc strong{color:var(--ink);font-weight:600}
.doc a{color:var(--accent-readable);font-weight:500;text-decoration:underline;text-decoration-color:rgba(224,99,58,.32);text-underline-offset:2px}
.doc a:hover{text-decoration-color:var(--accent-readable)}

/* The retention schedule. Its header band was #0f172a - a navy that appears
   nowhere else on the site - so it is now the same soft accent as the compare
   table on the home page, and separate borders so the corners can round. */
.doc-table{width:100%;border-collapse:separate;border-spacing:0;margin:4px 0 18px;font-size:15px;border:1px solid var(--line-dark);border-radius:14px;overflow:hidden}
.doc-table th{background:var(--accent-soft);color:var(--ink);text-align:left;padding:13px 16px;font-weight:600;font-size:13.5px;letter-spacing:.02em}
.doc-table td{padding:13px 16px;color:var(--muted);border-top:1px solid var(--line-dark);vertical-align:top;line-height:1.6}
.doc-table tbody tr:nth-child(even) td{background:var(--tint)}

/* ---------- the two form cards ----------
   book-demo and the checklist lead magnet. Byte-identical CSS on both pages
   apart from seven rules the checklist adds for its download button. */
.form-wrap{background:var(--paper);border:1px solid var(--line-dark);border-radius:22px;box-shadow:0 10px 34px rgba(17,22,29,.07);max-width:560px;margin:0 auto;padding:clamp(28px,4vw,44px)}
/* /book-demo wants the card at the width the Calendly embed used to occupy,
   not the 560 the checklist form uses. */
.form-wrap.form-wide{max-width:760px}
.form-wrap h2{font-family:var(--display);font-size:22px;font-weight:600;letter-spacing:-.015em;margin-bottom:7px;color:var(--ink)}
.form-wrap .sub{font-size:14.5px;color:var(--muted);margin-bottom:24px}
.demo-form{display:grid;grid-template-columns:1fr 1fr;gap:18px}
/* The heading and its subtitle are children of the form, so without this they
   are grid ITEMS and land in one column each - the title on the left, the
   sentence under it beside it rather than below. The error box already had its
   own grid-column, which is why it was the only one of the three that behaved. */
.demo-form > h2,.demo-form > .sub{grid-column:1 / -1}
.demo-form > h2 + .sub{margin-top:-15px}
.demo-field{display:flex;flex-direction:column;gap:7px}
.demo-field.full{grid-column:1 / -1}
.demo-field label{font-size:13px;font-weight:600;color:var(--ink)}
.demo-field input{width:100%;border:1px solid var(--line-dark);border-radius:11px;padding:12px 14px;font-size:15px;outline:none;font-family:var(--sans);color:var(--ink);background:var(--paper);transition:border-color .2s,box-shadow .2s}
.demo-field input:focus{border-color:var(--accent-readable);box-shadow:0 0 0 3px rgba(224,99,58,.14)}
.demo-submit{grid-column:1 / -1;border:none;border-radius:11px;padding:14px;background:var(--accent);color:var(--accent-ink);font-size:15.5px;font-weight:600;cursor:pointer;font-family:var(--sans);transition:background .2s,transform .15s}
.demo-submit:hover{background:var(--accent-hover);transform:translateY(-1px)}
.demo-submit:disabled{opacity:.6;cursor:not-allowed;transform:none}
.demo-error{grid-column:1 / -1;display:none;margin:0;padding:11px 13px;border-radius:11px;background:#fef2f2;color:#991b1b;font-size:13.5px;border:1px solid #fecaca}
.demo-success{text-align:center;padding:20px 0}
.demo-success .ic{width:56px;height:56px;border-radius:50%;background:#dcfce7;color:#15803d;font-size:26px;display:flex;align-items:center;justify-content:center;margin:0 auto 18px}
.demo-success h2{font-family:var(--display);font-size:22px;font-weight:600;letter-spacing:-.015em;margin-bottom:8px;color:var(--ink)}
.demo-success p{color:var(--muted);font-size:15px;margin-bottom:18px}
.demo-success .dl-btn{display:inline-block;border-radius:11px;padding:13px 26px;background:var(--accent);color:var(--accent-ink);font-size:14.5px;font-weight:600;transition:background .2s,transform .15s}
.demo-success .dl-btn:hover{background:var(--accent-hover);transform:translateY(-1px)}
.demo-success .demo-link{display:block;margin-top:14px;font-size:13.5px;color:var(--muted)}
.demo-success .demo-link a{color:var(--accent-readable);font-weight:600}
@media(max-width:520px){.demo-form{grid-template-columns:1fr}}

/* The four counts above the checklist form. Was its own four-column grid with
   its own card; it is the shared four-up grid now. */
.stat-row{max-width:920px;margin:0 auto;gap:20px 18px}
.stat-card{background:var(--paper);border:1px solid var(--line-dark);border-radius:14px;padding:20px}
.stat-card .num{font-family:var(--display);font-size:26px;font-weight:600;color:var(--accent-readable);margin-bottom:6px;line-height:1}
.stat-card p{font-size:13.5px;color:var(--muted);line-height:1.55}

/* ---------- /book-demo ----------
   That page is a page head and a third-party booking widget, nothing else, so
   it wants two things no other page does.

   The tint runs down the BODY rather than living inside the hero. .top-hero
   normally paints --tint-fade on itself, which fades to solid paper halfway
   down the hero and therefore dies well above the widget; .hero-bare turns
   that off so the body's single gradient runs uninterrupted from the top of
   the page past the calendar.

   The length is 1700px, which is longer than the page. Ending the fade exactly
   at the footer sounded right and was not: a linear fade to zero alpha is
   already down to 0.06 by the bottom of the widget, so the half of the page
   the tint was extended to cover had almost no tint on it. The footer has an
   opaque white background of its own, so it masks wherever the gradient is cut
   off - which means the fade can stay visible all the way down to it, at about
   0.17 where they meet, and the hairline border reads as the boundary.

   And the standard 88px/62px break between a page head and its first section
   left 184px of empty page above the widget, because the lede's own 34px
   bottom margin is on top of it. 18 + 28 + 34 is 80. */
.top-hero.hero-bare{background:none;padding-bottom:18px}
.sec.sec-snug{padding-top:28px}
/* hero-bare's sibling, for a page head that wants to sit close to its content
   but KEEP its tint. /credits is the case: a two-line lede and then 184px of
   nothing - the lede's own 34px, the hero's 88px and the section's 62px, all
   stacking the way they were measured doing on /book-demo. hero-bare fixes the
   same 184px but turns the background off with it, which is right for a page
   that is one booking widget and wrong for a page that is a document. */
.top-hero.hero-tight{padding-bottom:26px}
body.tint-top.tint-deep{background-size:100% 1700px}
