﻿/* ======================================================================
   THE SOFTWARE PAGE'S HERO: the application itself.

   One window with the product's own sidebar, a rail above it naming the
   four things the business actually keeps in there, and a caption that
   changes with the section. Every screen is the same size, the sidebar
   and the rail drive the same state from both ends, and the meeting
   runs.

   Built from /hero-v2, which was the review page for it.
   ====================================================================== */
/* ======================================================================
   A REVIEW PAGE. Everything is prefixed .swa- and nothing touches the
   real stylesheets.
   ====================================================================== */
.swa-note{max-width:820px;margin:0 auto;padding:70px 24px 36px}
.swa-note h1{
  font-family:'League Spartan',sans-serif;font-weight:700;
  font-size:clamp(28px,3.6vw,38px);line-height:1.05;letter-spacing:-.035em;
  text-transform:lowercase;margin:0 0 14px;
}
.swa-note p{font-size:16px;line-height:1.62;color:rgba(246,241,234,.7);margin:0 0 10px}
.swa-label{
  position:sticky;top:0;z-index:40;display:flex;gap:8px 16px;align-items:baseline;
  flex-wrap:wrap;padding:15px 24px;background:#0A0908;
  border-top:1px solid rgba(246,241,234,.14);
  border-bottom:1px solid rgba(246,241,234,.14);
}
.swa-label span{font-size:13px;letter-spacing:.16em;text-transform:uppercase;font-weight:700;color:#E4BCAC}
.swa-label em{font-style:normal;font-size:13.5px;color:rgba(246,241,234,.58)}

:root{
  /* THE SITE'S OTHER ACCENT, not the app's.
     The captures' own blue is #7CE2FE -- sampled off the Spin button and
     the completion bar -- but nothing else on next12 is that colour, and
     one electric blue in a warm palette reads as a foreign object. This
     is the slate the site already owns: home's "learn more" on the
     starting-point card, and the planning page's numerals and its
     ledger tag. #CFDCE8 is its lighter tint, off planning's "this
     quarter". */
  --swa-app-accent:#A9B8C6;

  /* ONE TYPE SCALE FOR THE WHOLE WINDOW.
     Measured across the first pass: a card title was 12, a row 11.5, a
     goal 11.5, a tab 11 and a sidebar item 11 -- five sizes doing three
     jobs, which is what made the mock feel assembled rather than
     designed. Four sizes now, and nothing in the frame is off them. */
  --ui-title:17px;   /* the view's name, once per view */
  --ui-head:12px;    /* card headers, nav items, tabs */
  --ui-body:11.5px;  /* every row of content */
  --ui-meta:10px;    /* dates, owners, counts */
  --ui-micro:8.5px;  /* uppercase labels */
}

/* ---------------------------------------------------------------- the hero */
.sw-hero-simple{
  position:relative;overflow:hidden;text-align:center;
  background-color:var(--sw-ground-dark);
  /* 128 at every width now, down from 148 on desktop -- her call off a
     rendered ladder at 148/128/112. The phone was already 128, so this
     is desktop coming down to meet it rather than a new number, and the
     copy now sits 24px below the masthead instead of 44. Planning's hero
     moves with it; the two were matched at 148 and stay matched at 128. */
  padding:128px 24px 0;
}
.sw-hero-simple::before{
  content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  /* cover, so it reaches the top edge of the page.
     `125% auto` zoomed in but rendered the picture 720px tall inside a
     1100px section, which left flat ground colour above and below it --
     the top of the page was not the photograph at all. cover fills the
     whole section, and because the section is now half as tall again as
     it was, cover IS the close crop: it scales to the height and throws
     away about half the width. */
  /* The dusk frame, resampled -- see THE FRAMES TRADE PLACES at the foot
     of this file for why it is a .webp and not the .jpg it arrived as. */
  background:url("/assets/images/desert-dusk.webp") center 62%/cover no-repeat;
  background-image:image-set(url("/assets/images/desert-dusk.avif") type("image/avif"),url("/assets/images/desert-dusk.webp") type("image/webp"));
  /* was saturate(.68) brightness(.92), which was for the dusk frame.
     This one is already cool and low-contrast; knocking it down again
     only made it muddy. */
  filter:saturate(.8) brightness(.95);
}
/* LIGHTER BY A QUARTER, AND THE QUARTER IS MEASURED.

   Every stop and the flat layer under them scaled by 0.74. Scaling the
   whole wash rather than lifting one number keeps the shape of it --
   the dip at 54% is there to sit the caption on something darker and
   that relationship should survive the change.

   The binding constraint is not the 56px headline, which is large text
   at 3:1. It is the three small things: the 12px eyebrow at .70, the
   13px tab labels at .78 and the 15.5px caption at .74, all of which
   need 4.5. Measured against the brightest ground pixel in the strip
   each one actually occupies:

     x1.00   eyebrow 7.34   tabs 7.85   caption 6.98
     x0.86   eyebrow 6.82   tabs 6.91   caption 6.08
     x0.74   eyebrow 6.31   tabs 6.22   caption 5.37
     x0.62   eyebrow 5.80   tabs 5.45   caption 4.67

   x0.62 still passes but leaves the caption 0.17 of headroom, and the
   crop moves with viewport height, so the bright patch behind it is not
   fixed. x0.74 is a real lightening with margin to spare. */
.sw-hero-simple::after{
  content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:
    linear-gradient(180deg,
      rgba(15,13,12,.37) 0%, rgba(15,13,12,.22) 26%, rgba(15,13,12,.22) 42%,
      rgba(15,13,12,.31) 54%, rgba(15,13,12,.27) 68%, rgba(15,13,12,.18) 84%,
      rgba(15,13,12,.30) 100%),
    rgba(23,20,19,.46);
}
/* Every child that has to be seen has to be named. The wash sits on
   ::after at z-index 1, so anything left off this list paints underneath
   it -- which is exactly what happened to the cue the first time. */
.sw-hero-simple > .swa-copy,
.sw-hero-simple > .swa-cue,
.sw-hero-simple > .sw-hero-rail,
.sw-hero-simple > .swa-stage{position:relative;z-index:2}
/* The masthead keeps the absolute position home and planning give it,
   so the wordmark lands at y=26 the way it does on both of them. It
   only ever needed the z-index to clear the wash. */
.sw-hero-simple > .n12-head{z-index:3}
.swa-copy .eyebrow{display:block;margin-bottom:14px}
.swa-copy h1{
  font-family:'League Spartan',sans-serif;font-weight:700;
  font-size:var(--n12-h1);line-height:1.02;letter-spacing:-.035em;
  text-transform:lowercase;color:#F6F1EA;margin:0 auto 24px;
}
.swa-br{display:inline}
/* IT HAS TO BE READ TO DO ITS JOB.
   At 8.5px and .32 it was decoration -- present enough to satisfy me
   that the page had said it, invisible enough that nobody would ever
   find out. A tag: bordered, plated, at .62, square-cornered like the
   rest of the site. Small, but findable. */
/* Out of the window's corner and put where it does some work: directly
   above the ask, pointing at it. In the corner it was a disclaimer you
   might notice; here it is the reason to press the button under it. */
.swa-disclaimer{
  position:relative;margin:26px auto 0;max-width:54ch;text-align:center;
  font-size:13px;line-height:1.5;color:rgba(246,241,234,.56);
}
.swa-disclaimer::after{
  content:"";display:block;width:1px;height:18px;margin:11px auto 0;
  background:linear-gradient(180deg,rgba(228,188,172,0),rgba(228,188,172,.8));
}
.swa-actions{display:flex;justify-content:center;margin:12px 0 0;padding-bottom:4px}

/* THE RAIL SPANS THE WINDOW IT DRIVES.
   software-n12.css caps it at 760 for the live hero, where it stands
   over a fanned stack. Here it stands over a 1060px application window,
   and at 760 it read as a separate widget floating above a screenshot.
   Matched to the window, the four nodes line up with the thing they
   open and the two read as one object. */
.sw-hero-simple .sw-hero-rail{width:min(100%,1060px)}

/* THE LIGHT THAT RUNS THE RAIL.
   The spine on the home page carries colour along it as you scroll;
   this is the same idea on a switch. A spark sits on the line at the
   selected node and slides to the next one when you pick it, so the two
   points are visibly connected rather than one just going out and
   another coming on. It only shows while it is travelling. */
/* `.sw-hero-rail .swa-spark`, not `.swa-spark`.
   software-n12.css carries `.sw-hero-rail i{transition:color .25s}` for
   the step numerals -- specificity 0,1,1 -- and the spark is an <i>, so
   a bare `.swa-spark` rule at 0,1,0 lost the transition property
   entirely and the light teleported. Measured: two positions, 12.5%
   then 87.5%, nothing in between.

   z-index 3 so it passes OVER the cue's plate rather than behind it: it
   is only on screen for half a second, and a light that disappears
   halfway looks like a fault. */
.sw-hero-rail .swa-spark{
  position:absolute;top:22px;left:12.5%;z-index:3;
  /* The same size as the node, so it settles INTO the destination
     rather than landing as a smaller, unrelated dot inside it. */
  width:13px;height:13px;border-radius:999px;margin:0;
  background:#E4BCAC;box-shadow:0 0 12px 4px rgba(228,188,172,.45);
  transform:translate(-50%,-50%);opacity:0;pointer-events:none;
  transition:left .55s cubic-bezier(.4,0,.2,1),top .55s cubic-bezier(.4,0,.2,1),opacity .3s ease;
}
.sw-hero-rail.is-travelling .swa-spark{opacity:1}
@media(prefers-reduced-motion:reduce){
  .sw-hero-rail .swa-spark{transition:none;display:none}
}
@media(max-width:760px){
  /* The rail stands up here, so the light runs down it instead. */
  .sw-hero-rail .swa-spark{top:8px;left:6px}
}

/* ---------------------------------------------------------------- the cue */
/* THE CUE SITS IN A BREAK IN THE RAIL.
   It was a bordered pill on its own row above the rail: another thing
   to look at in a hero that already had six, and on section 01 it was
   the third row before you even reached the window.

   Instead the rail's line is drawn as two segments with a gap in the
   middle -- between 02 and 03 -- and the cue lives in the gap. It costs
   no height, and a deliberate break in a line is itself a signal that
   something belongs there.

   Clay, not the slate: the slate belongs to the window -- the nav, the
   run pill, the open seat -- and a cue in the same colour read as part
   of the app rather than as the page talking to you. */
.sw-hero-simple .sw-hero-rail::before{left:12.5%;right:59%}
.sw-hero-simple .sw-hero-rail::after{
  content:"";position:absolute;left:59%;right:12.5%;top:22px;height:1px;
  background:rgba(246,241,234,.2);
}
.swa-cue{
  position:absolute;left:50%;top:22px;transform:translate(-50%,-50%);
  z-index:2;margin:0;padding:0;
  display:inline-flex;align-items:center;
  /* No plate, no blur, no border. The gap in the line is the frame --
     anything else round it was a box on a box. */
}
.swa-cue span{
  display:flex;align-items:center;padding:0 4px;white-space:nowrap;
  font-size:13.5px;letter-spacing:.02em;color:#E4BCAC;
}
/* Plain chevrons either side, sitting on the line. */
.swa-cue button{
  font:inherit;font-size:17px;line-height:1;cursor:pointer;
  background:none;border:0;padding:3px 7px;color:#E4BCAC;
  transition:color .2s ease,transform .9s ease-in-out;
}
.swa-cue button:hover{color:#FFE7DA}
.swa-cue button:focus-visible{outline:2px solid #E4BCAC;outline-offset:-2px}
/* They drift apart and come back, along the line they are sitting on. */
.swa-cue.is-nudge button:first-child{transform:translateX(-3px)}
.swa-cue.is-nudge button:last-child{transform:translateX(3px)}
@media(prefers-reduced-motion:reduce){
  .swa-cue button{transition:color .2s ease,background .2s ease}
  .swa-cue.is-nudge button{transform:none}
}
@media(max-width:760px){
  /* The rail stands up here, so there is no middle of a line to sit in:
     the cue goes back under it as an ordinary row. */
  .sw-hero-simple .sw-hero-rail::before{left:6px;right:auto;top:8px;bottom:8px;width:1px;height:auto}
  .sw-hero-simple .sw-hero-rail::after{display:none}
  .swa-cue{
    position:static;transform:none;grid-column:1/-1;justify-self:center;
    margin:14px 0 0;background:none;backdrop-filter:none;
  }
}

/* ------------------------------------------------------------- the caption
   NO MINI-HEADLINE. It carried "know what's getting done." above the
   paragraph -- which is a third heading in a hero that already has a
   headline and a rail label, all three saying the same thing in
   different words. The sentence alone does the work. */
/* 35 rather than 22, and the 13 is measured rather than judged.

   THE TWO GAPS IN THIS HERO ARE MEANT TO MATCH, and they did not,
   because CSS margins run from the LINE BOX and the eye runs from the
   letters. A line box is always taller than the type in it: the leftover
   between the font's line-height and its cap height splits above and
   below as half-leading, so two gaps that are identical in CSS look
   different whenever the two elements are set at different sizes.

   Measured off painted pixels -- first and last row of actual ink, every
   other element in the hero hidden so nothing borrows a neighbour's
   descender:

     headline ink bottom -> tab label ink top    46.2px   (40 declared)
     rail underline      -> caption ink top      33.0px   (27 declared)

   The caption carries 6px of half-leading above it and the tab label
   3px, which is why the declared gap and the seen gap differ by more on
   one than the other. 22 + 13 = 35 closes the painted gap to 46.
   ====================================================================== */
.swa-capwrap{
  display:flex;align-items:center;justify-content:center;gap:20px;
  margin:35px auto 14px;
}
/* Wide enough that the longest of them -- 02, whose second sentence
   runs 113 characters -- lands on two lines rather than three. All four
   are two lines now, so the block is the same shape on every section
   and nothing below it moves. */
.swa-cap{
  max-width:104ch;font-size:15.5px;line-height:1.58;color:rgba(246,241,234,.74);
}
@media(max-width:760px){
  .swa-capwrap{flex-direction:column;gap:14px}
}
/* ALL EIGHT IN ONE CELL, so the box is always as tall as the tallest
   and the window below it never moves.

   The captions run from one line to five depending on the section and
   the width, and with display:none the box collapsed to whichever one
   was showing -- so changing section slid everything underneath it by
   up to 31px on a desktop and 68 on a phone. Stacking them in a single
   grid area means the row is sized by the longest one at whatever width
   you are at, with no measured numbers to go stale.

   visibility, not display: it keeps the hidden ones in the layout while
   taking them out of the accessibility tree. */
.swa-cap{display:grid}
.swa-cap > span{grid-area:1/1;visibility:hidden}
.swa-cap > span.is-on{visibility:visible}

/* ============================== THE APP FRAME ========================= */
.swa-stage{max-width:1060px;margin:14px auto 0}
/* Rounded, like the application it is a picture of -- and unlike the
   page around it, which is square everywhere. That difference is doing
   work: it is what says this is a window sitting on the page rather
   than another band of the page. */
.swa-app{
  position:relative;border-radius:12px;
  background:#161314;border:1px solid rgba(246,241,234,.1);
  /* NO DROP SHADOW AT ALL.

     This started as one 90px blur at .66, which banded into visible
     rings; splitting it into three shorter layers measured smooth --
     stepping by at most 1.5 luminance points across 110px -- and she
     still saw the ring. The measurement was answering the wrong
     question. A black shadow over a near-black ground has almost no
     contrast to spend, so what little it does paint sits as a dark halo
     offset below the window rather than reading as depth. Smoothing the
     ramp does not help, because the halo IS the shadow.

     The window separates from the band by being lighter than it and by
     its own 1px edge, which is how a lit screen on a dark ground
     actually looks. Same removal on .pl-plan-window.

     BUT WITH NO SHADOW AT ALL IT WENT FLAT, which she said straight
     away. Depth on a dark ground comes from light, not from shade: a
     hairline of cream along the top edge reads as the screen catching
     the room, and a short, tight, nearly-offset-free shadow reads as
     contact with the page. The thing that made a halo was a LONG blur
     carrying alpha far out from the edge -- 12px reaches nowhere, so it
     seats the window without drawing a ring round it. */
  box-shadow:
    inset 0 1px 0 rgba(246,241,234,.10),
    0 1px 2px rgba(0,0,0,.55),
    0 4px 12px rgba(0,0,0,.35);
  /* THE SAME FADE AS HOME'S HERO PHOTOGRAPH. That one is .n12-photo on
     the reveal system's "fade" variant -- opacity .9s ease, no delay and
     no movement. This was the default reveal: opacity AND transform over
     .6s on a cubic-bezier with a .28s delay, so it arrived faster, later
     and with a rise. Specificity beats .rv [data-rv] so the base state
     still hides it; only the arrival changes. */
  text-align:left;overflow:hidden;
}
/* NO REVEAL OVERRIDE HERE, DELIBERATELY.

   This carried one briefly, to make the mock fade like home's hero
   photograph -- opacity .9s ease, no delay, no rise. It broke the fade
   outright: measured, opacity was already 1 at 61ms where the untouched
   reveal traced a proper 0 -> 1 ramp. Restating the transition from
   outside the reveal system is enough to stop it firing, because the
   reveal class lands before first paint on anything already in view and
   there is then no starting frame to transition from. The mock appeared
   instantly while its own 35 animating children were still running,
   which is what read as shuddering.

   The system's own timing works. If these ever should match home's
   exactly, the way to do it is to give them the system's "fade" variant
   in the markup -- data-rv="fade", which reveal-n12.css already defines
   at opacity .9s ease -- not to restate the transition over the top. */
.swa-app-bar{
  display:flex;align-items:center;gap:7px;
  padding:11px 14px;border-bottom:1px solid rgba(246,241,234,.07);
  background:#1D1A1B;
}
.swa-app-bar u{
  width:9px;height:9px;border-radius:999px;text-decoration:none;
  background:rgba(246,241,234,.22);
}
.swa-app-bar u:nth-child(3){background:rgba(178,132,121,.75)}
.swa-app-bar p{margin:0 0 0 10px;font-size:11px;color:rgba(246,241,234,.5)}
/* EVERY VIEW IS THE SAME SIZE. They were four different heights, so the
   window changed shape under you every time you pressed the rail -- and
   a window that resizes when you look at it is a slideshow, not an app. */
/* The floor is set by the fullest screen -- the plan -- so the other
   seven pad up to meet it rather than the plan being squeezed down. */
.swa-app-body{display:grid;grid-template-columns:196px minmax(0,1fr);min-height:480px}
/* THE PHONE MENU BUTTON DOES NOT EXIST ON A DESKTOP.

   It lives in the markup inside .swa-app-body and every rule styling it
   sits in the phone block -- so above 760 it fell through to the
   browser's default button: a grey box, in the flow, as the first grid
   item of a two-column grid. It pushed the sidebar and the view into the
   wrong tracks and broke the window outright.

   Declared here rather than only hidden in the phone block, because a
   control that belongs to one breakpoint should be absent at every other
   by default rather than absent wherever someone remembered. */
.swa-burger{display:none}

/* ---------------------------------------------------------- the sidebar */
.swa-nav{
  border-right:1px solid rgba(246,241,234,.07);
  padding:14px 0 16px;background:#131011;
  display:flex;flex-direction:column;
}
.swa-brand{display:flex;align-items:center;gap:9px;padding:0 14px 14px}
.swa-brand i{
  font-style:normal;display:grid;place-items:center;width:20px;height:20px;
  border-radius:6px;background:#2A2422;color:#E4BCAC;
  font-family:'League Spartan',sans-serif;font-weight:700;font-size:10px;
}
.swa-brand b{font-size:var(--ui-head);font-weight:400;color:rgba(246,241,234,.86)}
.swa-nav ul{list-style:none;margin:0;padding:0}
.swa-nav li{
  padding:7px 14px;font-size:var(--ui-head);color:rgba(246,241,234,.5);
  border-left:2px solid transparent;
  transition:color .25s ease,background .25s ease;
}
/* THE FOUR THE RAIL DRIVES ARE REAL BUTTONS. The rest are listed and
   inert -- they are there to say how much is in one place, and I have no
   captures of Reports, Directory, Drive or Automations to build them
   from. Making them up would be the one kind of lie this page cannot
   afford. */
.swa-nav li[data-nav]{cursor:pointer}
.swa-nav li[data-nav]:hover{color:rgba(246,241,234,.85);background:rgba(246,241,234,.04)}
.swa-nav li.is-on{
  color:#F6F1EA;background:rgba(246,241,234,.05);
  border-left-color:var(--swa-app-accent);
}
.swa-nav hr{border:0;border-top:1px solid rgba(246,241,234,.07);margin:12px 14px}
.swa-nav small{
  display:block;padding:0 14px 6px;font-size:var(--ui-micro);letter-spacing:.14em;
  text-transform:uppercase;color:rgba(246,241,234,.3);
}
.swa-user{
  margin-top:auto;display:flex;align-items:center;gap:8px;padding:12px 14px 0;
  border-top:1px solid rgba(246,241,234,.07);
}
.swa-user i{
  font-style:normal;display:grid;place-items:center;width:22px;height:22px;
  border-radius:999px;background:#2A2422;color:#E4BCAC;
  font-size:var(--ui-micro);font-weight:700;
}
.swa-user b{display:block;font-size:var(--ui-meta);font-weight:400;color:rgba(246,241,234,.7)}
.swa-user em{display:block;font-size:var(--ui-micro);font-style:normal;color:rgba(246,241,234,.36)}

/* ------------------------------------------------------------- the views */
/* Room at the foot for the note in the corner, so nothing runs under it. */
.swa-view{display:none;padding:15px 18px 32px}
.swa-view.is-on{display:block}
.swa-view-head{display:flex;align-items:center;gap:12px;margin-bottom:13px}
/* LOWERCASE. League Spartan is never set in caps anywhere on this site,
   and the app's own Title Case was the one place the window stopped
   speaking in the site's voice. */
.swa-view-head h2{
  margin:0;flex:1 1 auto;
  font-family:'League Spartan',sans-serif;font-weight:700;
  font-size:var(--ui-title);letter-spacing:-.02em;color:#F6F1EA;
  text-transform:lowercase;
}
.swa-chip{
  font-size:var(--ui-meta);padding:6px 11px;border-radius:5px;
  border:1px solid rgba(246,241,234,.14);color:rgba(246,241,234,.55);
  background:none;
}
/* The one control in the window that is the page's rather than the
   product's, so it is clay where everything else in here is slate. */
.swa-planlink{
  display:inline-flex;align-items:center;gap:7px;white-space:nowrap;
  font-size:var(--ui-meta);font-weight:700;padding:6px 12px;
  color:#E4BCAC;text-decoration:none;
  border:1px solid rgba(178,132,121,.5);
  transition:color .2s ease,border-color .2s ease,background .2s ease;
}
.swa-planlink:hover{color:#FFE7DA;border-color:#E4BCAC;background:rgba(228,188,172,.12)}
.swa-planlink em{font-style:normal;transition:transform .2s ease}
.swa-planlink:hover em{transform:translateX(3px)}
/* THE RUN CONTROL IS UP HERE NOW, where the app's own primary action
   sits, in the app's own blue. It was a text link under the agenda --
   below the fold of the window on a laptop, which is a strange place to
   put the one thing on the page you want pressed. */
.swa-run{
  font:inherit;font-size:var(--ui-head);font-weight:700;
  padding:8px 16px;border-radius:999px;border:0;cursor:pointer;
  background:var(--swa-app-accent);color:#12100F;
  transition:background .2s ease,transform .2s ease;
}
.swa-run:hover{background:#CFDCE8}
.swa-run:focus-visible{outline:2px solid #fff;outline-offset:2px}
.swa-run.is-live{background:rgba(169,184,198,.16);color:var(--swa-app-accent);box-shadow:inset 0 0 0 1px rgba(169,184,198,.55)}
/* A ring that expands and goes, so the pill is findable without the
   label moving. Stops at the first press. */
.swa-run-wrap{position:relative;display:inline-flex}
/* Same trap as .swa-pair, and I walked into it twice: [hidden] is a UA
   rule setting display:none, and the class above sets display:inline-flex,
   which beats it. The run pill was showing on every section. */
.swa-run-wrap[hidden]{display:none}
.swa-run-wrap::after{
  content:"";position:absolute;inset:-4px;border-radius:999px;
  border:1px solid var(--swa-app-accent);opacity:0;pointer-events:none;
  animation:swa-ping 3s ease-out infinite;
}
/* It used to stop at the first press. It pulses for good now: this is a
   still picture of an application, and the ring is the only thing in it
   that says otherwise. (.is-used is 0,2,0 and beat the rule that starts
   the animation further down the file, which is why the button went
   quiet the moment anyone touched it.) */
@keyframes swa-ping{
  0%{opacity:.5;transform:scale(.86)}
  60%,100%{opacity:0;transform:scale(1.16)}
}
@media(prefers-reduced-motion:reduce){.swa-run-wrap::after{animation:none}}

.swa-card{border:1px solid rgba(246,241,234,.08);background:#1B1819;border-radius:8px;overflow:hidden}
.swa-card + .swa-card{margin-top:11px}
/* ...but not side by side. The adjacent-sibling rule was putting 11px
   on the second card of every pair, so the two columns of the dashboard
   started 11px apart -- the headers off by a line and the whole right
   column sitting low. */
.swa-pair > .swa-card + .swa-card{margin-top:0}
.swa-card > h3{
  margin:0;padding:11px 14px;font-size:var(--ui-head);font-weight:400;
  color:rgba(246,241,234,.82);border-bottom:1px solid rgba(246,241,234,.06);
  font-family:'Questrial',sans-serif;text-transform:none;letter-spacing:0;
}
.swa-pair{display:grid;grid-template-columns:1fr 1fr;gap:11px}
/* [hidden] is a UA rule setting display:none, and a class that sets
   display beats it. Both plan horizons were rendering at once and the
   view came out 625px against everything else's 488 -- while the test
   read the .hidden PROPERTY and reported it correctly hidden. */
.swa-pair[hidden]{display:none}
@media(max-width:640px){.swa-pair{grid-template-columns:1fr}}

.swa-tabs{display:flex;gap:18px;padding:10px 14px 0;border-bottom:1px solid rgba(246,241,234,.06)}
.swa-tabs button{
  position:relative;background:none;border:0;padding:0 0 9px;cursor:pointer;
  font:inherit;font-size:var(--ui-head);color:rgba(246,241,234,.5);
}
.swa-tabs button[aria-selected="true"]{color:#F6F1EA}
.swa-tabs button[aria-selected="true"]::after{
  content:"";position:absolute;left:0;right:0;bottom:-1px;height:2px;background:var(--swa-app-accent);
}
.swa-tabs button:focus-visible{outline:2px solid var(--swa-app-accent);outline-offset:2px}

.swa-rows{padding:3px 14px 9px}
.swa-row{
  display:grid;grid-template-columns:15px minmax(0,1fr) auto auto;
  gap:10px;align-items:center;padding:8px 0;font-size:var(--ui-body);
  border-bottom:1px solid rgba(246,241,234,.05);
  background:none;border-left:0;border-right:0;border-top:0;width:100%;
  text-align:left;font-family:inherit;color:inherit;
}
.swa-row:last-child{border-bottom:0}
button.swa-row{cursor:pointer}
button.swa-row:hover{background:rgba(246,241,234,.03)}
button.swa-row:focus-visible{outline:2px solid var(--swa-app-accent);outline-offset:-2px}
.swa-row s{
  width:13px;height:13px;border-radius:3px;text-decoration:none;
  border:1px solid rgba(246,241,234,.3);transition:background .2s ease,border-color .2s ease;
}
.swa-row.done s{position:relative;background:#7FA98B;border-color:#7FA98B}
.swa-row.done s::after{
  content:"";position:absolute;left:3.5px;top:1px;width:4px;height:7px;
  border-right:1.5px solid #131011;border-bottom:1.5px solid #131011;transform:rotate(42deg);
}
.swa-row.done b{color:rgba(246,241,234,.42);text-decoration:line-through}
.swa-row b{font-weight:400;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:rgba(246,241,234,.88)}
.swa-row em,.swa-row strong{font-size:var(--ui-meta);font-style:normal;font-weight:400;color:rgba(246,241,234,.44)}
.swa-row strong{color:#E4BCAC}

/* the numbered list of goals, as the real Business Plan shows them */
/* Tightened so the plan -- the fullest screen in the app, two panels of
   figures, metrics and five written goals -- fits the same box as the
   rest. It was coming out 538 against everything else's 488. */
.swa-list{margin:0;padding:8px 14px 10px 28px;font-size:var(--ui-body);line-height:1.62;color:rgba(246,241,234,.82)}
.swa-list li{padding:1.5px 0}
.swa-list li::marker{color:rgba(246,241,234,.4)}
.swa-facts{padding:8px 14px}
.swa-fact{display:flex;justify-content:space-between;gap:12px;padding:4px 0;font-size:var(--ui-body)}
.swa-fact span{color:rgba(246,241,234,.5)}
.swa-fact b{font-weight:400;color:#F6F1EA}
.swa-sub{
  padding:8px 14px 2px;font-size:var(--ui-micro);letter-spacing:.14em;
  text-transform:uppercase;color:rgba(246,241,234,.4);
}
.swa-planning + *{margin-top:0}

/* ===================== THE MEETING, AS IT ACTUALLY WORKS ===============
   The agenda is not a list with a clock on it. In the real product it is
   a RAIL THAT DRIVES THE SCREEN: check in brings up the prompt, the
   numbers bring up the scorecard, opportunities brings up the issue
   list, and so on. That is the whole argument for running a meeting in
   here rather than off a printed agenda, and a static list was throwing
   it away.

   So the rail is on the left and the pane changes with it -- by hand if
   you click, and on its own while the meeting runs. */
.swa-meet{display:grid;grid-template-columns:186px minmax(0,1fr);gap:11px;align-items:start}
.swa-rail-card{
  border:1px solid rgba(246,241,234,.08);background:#1B1819;border-radius:8px;overflow:hidden;
}
.swa-rail-card > h3{
  margin:0;padding:10px 12px;font-size:var(--ui-head);font-weight:400;
  color:rgba(246,241,234,.82);border-bottom:1px solid rgba(246,241,234,.06);
  font-family:'Questrial',sans-serif;
}
.swa-ag{
  display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px;align-items:center;
  width:100%;padding:9px 12px;font-family:inherit;font-size:var(--ui-body);
  background:none;border:0;border-left:2px solid transparent;
  border-bottom:1px solid rgba(246,241,234,.05);
  text-align:left;cursor:pointer;color:inherit;
  transition:color .3s ease,background .2s ease,border-color .3s ease;
}
.swa-ag:last-child{border-bottom:0}
.swa-ag:hover{background:rgba(246,241,234,.04)}
.swa-ag:focus-visible{outline:2px solid var(--swa-app-accent);outline-offset:-2px}
.swa-ag b{font-weight:400;color:rgba(246,241,234,.8);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.swa-ag em{font-style:normal;font-size:var(--ui-meta);color:rgba(246,241,234,.4);font-variant-numeric:tabular-nums}
.swa-ag.is-on{background:rgba(246,241,234,.05);border-left-color:var(--swa-app-accent)}
.swa-ag.is-on b{color:#F6F1EA}
.swa-ag.is-live em{color:var(--swa-app-accent)}
.swa-ag.is-done b,.swa-ag.is-done em{color:rgba(246,241,234,.34)}
.swa-ag.is-done b{text-decoration:line-through}

.swa-pane{display:none}
.swa-pane.is-on{display:block}

/* check in */
.swa-prompt{padding:46px 20px;text-align:center}
.swa-prompt i{
  display:grid;place-items:center;width:54px;height:54px;margin:0 auto 14px;
  border-radius:999px;background:rgba(169,184,198,.12);
  font-style:normal;font-size:20px;color:var(--swa-app-accent);
}
.swa-prompt p{margin:0 auto;max-width:34ch;font-size:var(--ui-body);line-height:1.6;color:rgba(246,241,234,.72)}

/* the scorecard */
.swa-metrics{width:100%;border-collapse:collapse;font-size:var(--ui-body)}
.swa-metrics th{
  padding:9px 10px;text-align:left;font-weight:400;
  font-size:var(--ui-micro);letter-spacing:.12em;text-transform:uppercase;
  color:rgba(246,241,234,.42);border-bottom:1px solid rgba(246,241,234,.06);
}
.swa-metrics td{padding:8px 10px;border-bottom:1px solid rgba(246,241,234,.04);color:rgba(246,241,234,.84)}
.swa-metrics tr:last-child td{border-bottom:0}
.swa-metrics td.n{text-align:right;font-variant-numeric:tabular-nums}
.swa-metrics td.hit{background:rgba(127,169,139,.14);color:#A7C4A4}
.swa-metrics td.miss{background:rgba(190,110,95,.14);color:#E0A292}

/* priorities and opportunities share a row shape */
.swa-own{
  display:grid;grid-template-columns:22px minmax(0,1fr) auto;gap:10px;align-items:center;
  padding:8px 12px;font-size:var(--ui-body);border-bottom:1px solid rgba(246,241,234,.04);
}
.swa-own:last-child{border-bottom:0}
.swa-own i{
  font-style:normal;display:grid;place-items:center;width:22px;height:22px;border-radius:999px;
  font-size:var(--ui-micro);font-weight:700;color:#12100F;
}
.swa-own b{font-weight:400;color:rgba(246,241,234,.86);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.swa-pill{
  font-size:var(--ui-meta);padding:4px 9px;border-radius:999px;white-space:nowrap;
  border:1px solid rgba(246,241,234,.14);color:rgba(246,241,234,.6);
}
.swa-pill.on{border-color:rgba(127,169,139,.5);color:#A7C4A4}
.swa-pill.hold{border-color:rgba(190,110,95,.45);color:#E0A292}

/* the people strip, off the real meeting screen's attendee list */
.swa-who{display:flex;flex-wrap:wrap;gap:6px;padding:11px 14px}
.swa-who span{
  display:inline-grid;place-items:center;width:24px;height:24px;border-radius:999px;
  font-size:var(--ui-micro);font-weight:700;color:#12100F;
}
.swa-out{padding:11px 12px;border-top:1px solid rgba(246,241,234,.07)}
.swa-out > span{
  display:block;margin-bottom:7px;font-size:var(--ui-micro);letter-spacing:.14em;
  text-transform:uppercase;color:rgba(246,241,234,.4);
}
@media(max-width:860px){
  .swa-meet{grid-template-columns:1fr}
}

/* ================== THE ORG CHART, AS IT ACTUALLY LOOKS ===============
   The real one is a pannable canvas on a dot grid with curved
   connectors, cards that carry a role label, an avatar and the person,
   and a faint line under each for duties. It is asymmetric -- one lead
   has four reports, another has none -- which is the thing that makes
   it read as a real company rather than a diagram. The stacked flex
   version was a diagram.

   Positioned in a 1000x300 space so the cards and the SVG connectors
   share one coordinate system. On a phone the canvas pans, the way the
   real one does. */
.swa-canvas{
  position:relative;height:300px;min-width:700px;
  background-image:radial-gradient(rgba(246,241,234,.055) 1px,transparent 1px);
  background-size:17px 17px;
}
.swa-canvas-scroll{overflow-x:auto;overflow-y:hidden;border-radius:7px}
.swa-wires{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
.swa-wires path{fill:none;stroke:rgba(246,241,234,.2);stroke-width:1}
.swa-seat{
  position:absolute;width:128px;transform:translateX(-50%);
  padding:7px 9px 6px;border-radius:7px;
  border:1px solid rgba(246,241,234,.11);background:#191617;
}
.swa-seat > b{
  display:block;font-size:var(--ui-micro);font-weight:700;
  color:rgba(246,241,234,.5);text-transform:none;letter-spacing:.02em;
}
.swa-seat > span{
  display:flex;align-items:center;gap:6px;margin-top:5px;
  font-size:var(--ui-meta);color:#F6F1EA;
}
.swa-seat > span i{
  font-style:normal;flex:0 0 auto;display:grid;place-items:center;
  width:16px;height:16px;border-radius:999px;
  font-size:7px;font-weight:700;color:#12100F;
}
/* The name in its own box, so a long one truncates rather than running
   out past the card's edge. */
.swa-seat > span u{
  text-decoration:none;min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap;
}
.swa-seat > em{
  display:block;margin-top:5px;padding-top:5px;
  border-top:1px solid rgba(246,241,234,.06);
  font-style:normal;font-size:7.5px;color:rgba(246,241,234,.3);
}
.swa-seat.open > span{color:var(--swa-app-accent)}
.swa-seat.open > span i{background:rgba(169,184,198,.3);color:var(--swa-app-accent)}
/* the canvas controls, top right, as the real one carries */
.swa-zoom{
  position:absolute;top:8px;right:8px;display:flex;gap:5px;z-index:2;
}
.swa-zoom span{
  font-size:var(--ui-micro);padding:4px 8px;border-radius:5px;
  border:1px solid rgba(246,241,234,.12);background:rgba(20,17,18,.86);
  color:rgba(246,241,234,.5);
}

/* ------------------------------------------------- the four other screens */
.swa-stats{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:11px}
.swa-stat{padding:11px 12px;border-radius:8px;border:1px solid rgba(246,241,234,.08);background:#1B1819}
.swa-stat span{display:block;font-size:var(--ui-micro);letter-spacing:.12em;text-transform:uppercase;color:rgba(246,241,234,.42)}
.swa-stat b{
  display:block;margin-top:6px;font-family:'League Spartan',sans-serif;
  font-size:19px;font-weight:700;letter-spacing:-.02em;color:#F6F1EA;
}
.swa-stat b em{
  display:block;margin-top:3px;font-style:normal;font-weight:400;
  font-family:'Questrial',sans-serif;font-size:var(--ui-meta);
  letter-spacing:0;color:rgba(246,241,234,.42);
}

/* the planning offer, the same shape the spine used to carry */
.swa-planning{
  margin-top:9px;padding:8px 0 2px 15px;
  border-left:2px solid rgba(224,210,197,.34);
}
/* The plan is the fullest screen in the app and the only one that needs
   its rows tightened to sit in the same box as the other seven. */
[data-view="plan"] .swa-own{padding-top:6px;padding-bottom:6px}
.swa-planning > span{
  display:block;margin-bottom:6px;font-size:var(--ui-body);color:rgba(246,241,234,.6);
}
.swa-planning a{
  display:inline-flex;align-items:center;gap:7px;text-decoration:none;
  font-size:var(--ui-body);font-weight:700;color:#E0D2C5;
}
.swa-planning a:hover{color:#FFE7DA}
.swa-planning a em{font-style:normal;transition:transform .2s ease}
.swa-planning a:hover em{transform:translateX(3px)}
.swa-bars{padding:11px 14px}
.swa-barrow{display:grid;grid-template-columns:96px minmax(0,1fr);gap:11px;align-items:center;padding:6px 0}
.swa-barrow span{font-size:var(--ui-body);color:rgba(246,241,234,.62);text-align:right}
.swa-bar{display:flex;height:15px;border-radius:3px;overflow:hidden;background:rgba(246,241,234,.05)}
.swa-bar i{display:block;height:100%}
.swa-bar .ok{background:rgba(127,169,139,.85)}
.swa-bar .late{background:rgba(190,110,95,.85)}
.swa-bar .now{background:rgba(169,184,198,.8)}
.swa-legend{display:flex;gap:14px;padding:0 14px 10px;font-size:var(--ui-micro);color:rgba(246,241,234,.44)}
.swa-legend b{display:inline-block;width:9px;height:9px;border-radius:2px;margin-right:5px;vertical-align:-1px}

.swa-dir{width:100%;border-collapse:collapse;font-size:var(--ui-body)}
.swa-dir th{
  padding:9px 10px;text-align:left;font-weight:400;font-size:var(--ui-micro);
  letter-spacing:.12em;text-transform:uppercase;color:rgba(246,241,234,.42);
  border-bottom:1px solid rgba(246,241,234,.06);
}
.swa-dir td{padding:7px 10px;border-bottom:1px solid rgba(246,241,234,.04);color:rgba(246,241,234,.8);white-space:nowrap}
.swa-dir tr:last-child td{border-bottom:0}
.swa-dir td:first-child{display:flex;align-items:center;gap:8px;color:#F6F1EA}
/* the second line of the contact cell: extension or mobile */
.swa-dir td em{
  display:block;font-style:normal;font-size:var(--ui-micro);
  color:rgba(246,241,234,.4);margin-top:2px;
}
.swa-dir i{
  font-style:normal;display:grid;place-items:center;width:20px;height:20px;border-radius:999px;
  font-size:var(--ui-micro);font-weight:700;color:#12100F;
}

.swa-folders{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;padding:12px 14px}
.swa-folder{
  padding:14px 12px;border-radius:8px;border:1px solid rgba(246,241,234,.08);
  background:#1B1819;font-size:var(--ui-body);color:rgba(246,241,234,.84);
}
.swa-folder i{display:block;font-style:normal;font-size:15px;margin-bottom:8px;color:var(--swa-app-accent)}
.swa-folder em{display:block;margin-top:5px;font-style:normal;font-size:var(--ui-meta);color:rgba(246,241,234,.4)}

.swa-tools{display:grid;grid-template-columns:1fr 1fr;gap:10px;padding:12px 14px}
.swa-tool{
  padding:12px;border-radius:8px;border:1px solid rgba(246,241,234,.08);background:#1B1819;
}
.swa-tool b{display:block;font-size:var(--ui-body);font-weight:400;color:#F6F1EA;margin-bottom:5px}
.swa-tool p{margin:0;font-size:var(--ui-meta);line-height:1.5;color:rgba(246,241,234,.5)}
@media(max-width:860px){
  .swa-stats{grid-template-columns:repeat(3,1fr);gap:7px}
  .swa-stat{padding:9px 8px}
  .swa-stat b{font-size:16px}
  .swa-folders{grid-template-columns:repeat(2,1fr)}
  .swa-tools{grid-template-columns:1fr}
  .swa-oldest{display:none}
  /* The pairs stack here, so the plan -- two full panels -- would set a
     floor half again as tall as every other screen. The written goals
     go; the quarter's per-person list underneath says the same thing in
     the form that matters more on a phone. */
  [data-view="plan"] .swa-pair > .swa-card:first-child > .swa-list{display:none}
  [data-view="plan"] .swa-pair > .swa-card:first-child > .swa-sub:last-of-type{display:none}
}

@media(max-width:860px){
  /* Still one size, just a taller one: the two-column pairs stack here,
     so the tallest view sets the floor and the short ones pad out to
     meet it rather than the window shrinking under you. */
  .swa-app-body{grid-template-columns:1fr;min-height:643px}
  .swa-nav{
    border-right:0;border-bottom:1px solid rgba(246,241,234,.07);
    flex-direction:row;align-items:center;gap:0;padding:0;overflow-x:auto;
  }
  .swa-brand,.swa-nav hr,.swa-nav small,.swa-user{display:none}
  .swa-nav ul{display:flex;gap:0}
  .swa-nav li{border-left:0;border-bottom:2px solid transparent;white-space:nowrap;padding:11px 12px}
  .swa-nav li.is-on{border-left:0;border-bottom-color:var(--swa-app-accent);background:none}
  .swa-view{padding:14px 12px 16px}
  .swa-view-head h2{font-size:15px}
  .swa-view-head .swa-chip{display:none}

  /* ================= THE APP GETS A DRAWER ON A PHONE =================

     The sidebar turned into a horizontally scrolling row of eight labels
     here, which is not a thing an app does -- and four of the eight were
     always off the right edge, so half the product's nav was invisible
     unless you thought to swipe a strip that did not look swipeable.

     A drawer is the answer a real mobile app gives. The list slides in
     from the left of the WINDOW, not the page, so it reads as the app's
     own menu rather than the site's. Everything is scoped to .swa-app,
     so the page's own masthead menu is untouched.

     translateX is used rather than width or left, because it is the only
     one of the three that is composited -- on a phone the others animate
     on the main thread and stutter against the meeting demo running
     beside them. */
  .swa-app{position:relative;overflow:hidden}
  .swa-app-bar{position:relative;z-index:3}
  /* Top LEFT, inside the window. It sits over the view rather than in
     the flow, so the content below it does not shift when the drawer
     opens -- and the drawer slides out from directly beneath it, which
     is the whole reason for putting it on this side. */
  .swa-burger{
    display:flex;flex-direction:column;justify-content:center;gap:3.5px;
    position:absolute;left:11px;top:13px;z-index:3;
    width:32px;height:28px;padding:0 4px;
    border:0;border-radius:4px;background:none;cursor:pointer;
  }
  .swa-burger:active{background:rgba(246,241,234,.06)}

  /* THE SITE MENU'S CLOSE X WAS BEING PAINTED OVER.

     mobile-n12.css puts .n12-head at z-index 70 so the toggle stays
     above the full-screen menu at 60. This page overrides it to 3 --
     `.sw-hero-simple > .n12-head`, two selectors against one, so the
     override wins wherever it is declared. The X was drawn and then
     covered: measured with the menu open, the luminance across the
     toggle's whole rect was 7 to 7, a flat panel and nothing on it.

     Home and planning were fine, which is why it only showed here.

     Raised only while the menu is open, so the header's own stacking
     against the hero picture is unchanged the rest of the time. */
  .sw-hero-simple.is-menu-open > .n12-head{z-index:71}
  /* THE VIEW REACHES THE LEFT EDGE; ONLY ITS HEADING STEPS ASIDE.

     padding-left:52px indented the WHOLE view to clear the button, so
     every card and table below it sat in a 52px gutter that exists for a
     control in one corner -- a seventh of a 390px window given up down
     its entire height, and the reason the content looked inset from the
     frame.

     The heading row alone makes room now. Everything under it starts
     where the window starts. */
  .swa-view{padding-left:12px}
  .swa-view-head{padding-left:40px;min-height:28px}
  .swa-burger span{
    display:block;height:1.5px;background:rgba(246,241,234,.62);
    border-radius:1px;transition:transform .26s cubic-bezier(.33,1,.68,1),opacity .16s ease;
  }
  .is-appmenu .swa-burger span:nth-child(1){transform:translateY(4.5px) rotate(45deg)}
  .is-appmenu .swa-burger span:nth-child(2){opacity:0}
  .is-appmenu .swa-burger span:nth-child(3){transform:translateY(-4.5px) rotate(-45deg)}

  .swa-nav{
    position:absolute;top:0;bottom:0;left:0;z-index:2;
    width:196px;max-width:72%;
    flex-direction:column;align-items:stretch;gap:0;
    /* 52 at the top, not 12: the menu button sits at 13,11 inside the
       window and stays there while the drawer is open, so anything at
       the drawer's own top-left lands under it. At 12 that was the
       brand row -- the X drew straight over the "12" badge. The list
       starts below the button now. */
    padding:52px 0 16px;overflow-y:auto;overflow-x:hidden;
    border-right:1px solid rgba(246,241,234,.08);border-bottom:0;
    background:#131011;
    transform:translateX(-100%);
    transition:transform .28s cubic-bezier(.33,1,.68,1);
  }
  .is-appmenu .swa-nav{transform:translateX(0)}
  /* The brand line comes back -- in a drawer there is room for it, and it
     is what tells you whose menu this is. */
  .swa-brand{display:flex}
  .swa-nav hr,.swa-nav small,.swa-user{display:revert}
  /* The list goes back to a column. The 1024 block above sets
     `.swa-nav ul{display:flex}` for the horizontal strip this replaces,
     and it is still in force at 760 -- so the drawer opened with its
     eight items laid out in a row, spilling straight out of a 196px
     panel. Every declaration in the drawer rule was correct and the
     thing still rendered as a strip. */
  .swa-nav ul{display:block}
  .swa-nav li{white-space:nowrap;padding:9px 14px}

  /* The dimmed view behind it. Drawn on the body rather than as a
     separate node so there is nothing to add to the markup, and it only
     exists while the drawer is open. */
  .swa-app-body{position:relative}
  .swa-app-body::after{
    content:"";position:absolute;inset:0;z-index:1;
    background:rgba(9,7,7,.55);
    opacity:0;pointer-events:none;
    transition:opacity .22s ease;
  }
  .is-appmenu .swa-app-body::after{opacity:1;pointer-events:auto}

  /* THE ORG CHART IS THE ONLY VIEW THAT DOES NOT FIT, AND IT SCROLLS.

     Measured at 390: the app window is 348 wide and three of the four
     views have content exactly 348 wide. The org view's is 850, so 502px
     of it was simply cut off -- the owner's box at the top of the tree
     was never on screen at all.

     Scaling was tried first and rejected on the numbers. 348/850 is
     0.41, and the smallest type in this window is already 7px, so the
     whole chart would have come out at under 3px. A tree you cannot read
     is not a smaller tree, it is a texture.

     So it scrolls sideways instead, which is what a wide chart does on a
     phone in every app that has one. The fade on the right edge is the
     only thing telling you there is more -- without it a cut-off tree
     looks like a broken tree, which is how this one read.

     Only this view: the other three fit, and making them scrollable
     would put a scroll container around content that never moves. */
  /* The org tree stands up instead of scrolling -- declared at the END
     of this file, because .swa-tree's flex rules are at line 1294 and
     would win from there. See THE TREE STANDS UP below. */
}
@media(max-width:760px){
  .sw-hero-simple{padding-top:128px}
  .swa-br{display:none}
  .swa-cap{min-height:0;font-size:15px}
}


/* ======================================================================
   THE THREE SECTIONS AFTER THE HERO
   ====================================================================== */
/* Every value here is read off .sw-custom rather than chosen, so the new
   bands and the closing band are the same page and not two designs. */
/* 118/76, which is this page's rhythm -- .sw-product and .sw-custom both
   run it, and these bands were on 104 for no reason but that I picked it. */
.swx{padding:118px 0;background-color:var(--sw-ground)}
/* NO HAIRLINE BETWEEN BANDS. She asked whether tested-with-real-teams has
   a border, and it did -- this rule put a 1px cream .07 line above every
   band after the first, so three of the five carried one.

   Home and planning have none at all: checked every section on both, and
   the only thing separating their bands is the step between #171413 and
   #0F0D0C. The software page was the only one drawing a line as well,
   which is exactly the kind of difference that makes a page feel like it
   belongs to a different site without anyone being able to say why.

   The grounds already alternate here too, so the line was doing a job
   that was already done. */
/* THE PAGE'S OWN COLUMN, not a second one.

   .wrap on this page is width:100%, max-width:none, padding on
   --hx-inset -- that is what puts the left edge of the copy on the same
   line as the masthead's wordmark, and every other section obeys it.
   These bands were built on a centred 1160 box, which gave the page two
   different left edges depending on which section you were looking at. */
.swx-wrap{width:100%;max-width:none;margin:0;padding:0 var(--hx-inset)}
.swx-eyebrow{
  display:block;font-family:'Questrial',sans-serif;font-weight:700;
  font-size:12px;letter-spacing:.17em;text-transform:uppercase;
  color:#E4BCAC;margin:0 0 12px;
}
.swx h2{
  margin:0 0 22px;font-family:'League Spartan',sans-serif;font-weight:700;
  font-size:clamp(26px,2.65vw,38px);line-height:1.04;letter-spacing:-.035em;
  text-transform:lowercase;color:#F6F1EA;max-width:18ch;
}
.swx p{margin:0 0 16px;font-size:15px;line-height:1.6;color:rgba(246,241,234,.68);max-width:62ch}
.swx p:last-child{margin-bottom:0}

/* The original "who uses it" band lived here: a two-column .swx-proof
   grid and a .swx-card panel of bullets. Both were retired when that
   section became "no forced formula", and both are gone now.

   They had to go rather than sit dead, because I reused the name. The
   new one-sentence band was also called .swx-proof, so it silently
   inherited a two-column grid built for a layout that no longer
   existed -- which is why its centred paragraph was rendering
   left-aligned at two thirds width. Second time dead CSS matching a
   live selector has cost an hour; the rules go with the markup now. */

/* ------------------------------------------------------------ the price */
.swx-price .swx-wrap{text-align:center}
/* Capped at 38 rather than 50. Every section heading on all three pages
   is 38: home's four bands, planning's five including its closing band,
   and this page's other three. This one was the single exception, and a
   closing band is exactly where the site already has a precedent --
   planning's "let's get the next 12 months out of your head" is 38. */
/* THE FOOT'S HEADING SITS IN THE MIDDLE OF ITS OWN SPACE.

   Every other band on the site runs eyebrow and heading hard together --
   a 0px gap, matched to planning on purpose -- and then opens up under
   the heading. That is right where a paragraph follows. Here there is no
   paragraph: the heading is between a label and two buttons, and with
   2px above it and 29 below it was sitting on the eyebrow and floating
   off the buttons.

   Measured and split: 15 above, 15 below. Only this band -- the rule is
   the exception, not a change to the page's rhythm. */
.swx-price h2{max-width:none;margin-inline:auto;font-size:clamp(32px,4.2vw,38px);
  margin-top:13px;margin-bottom:8px}
/* The buttons come up to meet it. .swx-ctas carries margin-top:26 from
   its base rule, and the heading's own 8px sits on top of that, so the
   first attempt moved only the gap ABOVE the heading and left 29px
   below -- 15 and 29 instead of 15 and 15. Two classes here, so this
   wins wherever it sits. */
.swx-price .swx-ctas{margin-top:12px}
.swx-price p{margin-inline:auto}
.swx-price .swx-eyebrow{text-align:center}
.swx-note{
  display:inline-flex;align-items:center;gap:10px;margin-top:10px;
  padding:9px 16px;border:1px solid rgba(246,241,234,.14);
  font-size:13px;color:rgba(246,241,234,.62);
}
.swx-note b{color:#E4BCAC;font-weight:700}

/* ------------------------------------------------------------ the steps */
.swx-steps{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:0;margin-top:10px}
.swx-step{padding:26px 28px 6px;border-left:1px solid rgba(246,241,234,.1)}
.swx-step:first-child{padding-left:0;border-left:0}
.swx-step b{
  display:block;font-family:'League Spartan',sans-serif;font-weight:700;
  font-size:12px;letter-spacing:.14em;color:var(--sw-accent);margin-bottom:12px;
}
.swx-step strong{
  display:block;font-family:'League Spartan',sans-serif;font-weight:700;
  font-size:21px;line-height:1.1;letter-spacing:-.02em;color:#F6F1EA;
  text-transform:lowercase;margin-bottom:9px;
}
.swx-step span{display:block;font-size:13.5px;line-height:1.55;color:rgba(246,241,234,.66)}

@media(max-width:900px){
  .swx{padding:72px 0}
  /* the .swx-proof and .swx-step phone rules went with their sections */
}


/* ======================================================================
   THE REQUEST-A-LOGIN DIALOG

   A real <dialog>, so the focus trap, Esc, the backdrop and the inert
   page behind it are the browser's job and not a pile of my JavaScript.
   ====================================================================== */
.rql{
  width:min(560px,calc(100vw - 32px));max-height:calc(100vh - 48px);
  padding:0;border:1px solid rgba(246,241,234,.14);border-radius:12px;
  background:#1B1819;color:#F6F1EA;overflow:auto;
}
.rql::backdrop{background:rgba(9,8,7,.72)}
.rql-card{position:relative;padding:34px 36px 30px}
.rql-x{
  position:absolute;top:12px;right:14px;width:32px;height:32px;
  border:0;background:none;color:rgba(246,241,234,.5);
  font-size:26px;line-height:1;cursor:pointer;
}
.rql-x:hover{color:#F6F1EA}
.rql-eyebrow{
  display:block;margin:0 0 10px;font-family:'Questrial',sans-serif;font-weight:700;
  font-size:12px;letter-spacing:.17em;text-transform:uppercase;color:#E4BCAC;
}
.rql h2{
  margin:0 0 10px;font-family:'League Spartan',sans-serif;font-weight:700;
  font-size:30px;line-height:1.04;letter-spacing:-.035em;text-transform:lowercase;
}
.rql h2 .rql-name{text-transform:none}
.rql-lede{margin:0 0 22px;font-size:14.5px;line-height:1.55;color:rgba(246,241,234,.68)}
.rql-lede a{color:#E4BCAC}

.rql-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.rql-wide{grid-column:1/-1}
.rql-grid label{display:block}
.rql-grid label > span{
  display:block;margin-bottom:6px;
  font-family:'Questrial',sans-serif;font-size:11px;font-weight:700;
  letter-spacing:.12em;text-transform:uppercase;color:rgba(246,241,234,.5);
}
.rql-grid input,.rql-grid select,.rql-grid textarea{
  width:100%;box-sizing:border-box;padding:11px 12px;
  border:1px solid rgba(246,241,234,.16);border-radius:0;
  background:#171413;color:#F6F1EA;
  font-family:'Questrial',sans-serif;font-size:14.5px;line-height:1.4;
}
.rql-grid textarea{resize:vertical;min-height:72px}
.rql-grid input:focus,.rql-grid select:focus,.rql-grid textarea:focus{
  outline:0;border-color:var(--sw-accent,#B28479);
  box-shadow:inset 0 0 0 1px var(--sw-accent,#B28479);
}
/* Chrome paints its own near-white autofill background and the cream
   text disappears into it. The inset shadow is the only way back. */
.rql-grid input:-webkit-autofill{
  -webkit-text-fill-color:#F6F1EA;
  box-shadow:inset 0 0 0 40px #171413;
}
/* :user-invalid, not :invalid. An empty required field is invalid from
   first paint, and :not(:placeholder-shown) does not save it -- a field
   with no placeholder attribute is never :placeholder-shown -- so the
   form opened with three boxes already outlined in red, scolding
   someone who had not typed anything yet. :user-invalid waits for them
   to actually try. Where it is unsupported nothing turns red, which is
   the right way round to fail. */
.rql-grid input:user-invalid,
.rql-grid select:user-invalid{border-color:rgba(214,110,90,.75)}

.rql-go{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  margin-top:22px;padding:14px 26px;border:0;border-radius:0;cursor:pointer;
  font-family:'Questrial',sans-serif;font-size:16px;font-weight:700;line-height:1;
  background:var(--n12-cream,#F6F1EA);color:#000;
  transition:background .18s ease,transform .18s ease;
}
.rql-go:hover:not(:disabled){background:#fff;transform:translateY(-1px)}
.rql-go:disabled{opacity:.6;cursor:default}
.rql-note{margin:14px 0 0;font-size:12px;line-height:1.5;color:rgba(246,241,234,.45)}
.rql-note a{color:rgba(246,241,234,.7)}

@media(max-width:560px){
  .rql-card{padding:30px 22px 26px}
  .rql-grid{grid-template-columns:1fr}
  .rql h2{font-size:26px}
}

/* ---------------------------------------------------- the two triggers */
.swx-ctas{display:flex;flex-wrap:wrap;gap:12px 22px;align-items:center;justify-content:center;margin-top:26px}
.swx-price .swx-note{margin-top:22px}
.swx-steplink{
  display:inline-block;margin-top:11px;
  font-family:'Questrial',sans-serif;font-size:13.5px;
  color:#E4BCAC;border-bottom:1px solid rgba(228,188,172,.35);
  padding-bottom:2px;
}
.swx-steplink:hover{border-bottom-color:#E4BCAC}


/* ======================================================================
   THE PHONE PASS
   ====================================================================== */
@media(max-width:900px){
  /* THE GUTTER COMES BACK.

     mobile-n12.css carries
         .sw-hero-simple{padding-left:0 !important;padding-right:0 !important}
     which was right for the hero this replaced: a full-bleed photograph
     with .sw-hero-wrap inside it holding the type off the edges. This
     hero has no such wrapper -- its children sit straight in the
     section -- so that rule put every line of copy hard against both
     edges of the phone.

     Given to the children rather than fought with a counter-!important,
     because that rule is still correct for the other four sections it
     names. */
  .sw-hero-simple > .swa-copy,
  .sw-hero-simple > .swa-stage{padding-left:20px;padding-right:20px}

  /* The window keeps its corners. Edge to edge, the 12px radius was
     being cut off by the viewport on both sides, so the one thing in
     the hero that is deliberately round read as square. */
  .swa-app{border-radius:10px}

  /* The app's own type does not need to shrink with the frame -- it is
     a picture of software, and software on a phone is still 11px. But
     the frame itself was taller than the screen, so the disclaimer and
     the button below it were two scrolls past the thing they refer to. */
  .swa-app-body{min-height:0}
}

@media(max-width:760px){
  /* THE SPINE STOPS AT THE LAST NODE.

     Standing up, the line was drawn as one absolute bar from the top of
     the rail to the bottom -- and the cue is inside the rail, so the
     line ran on past the fourth node and down beside "take a look
     around", ending in mid-air.

     Drawn per button instead, so it exists exactly where there are
     steps and nowhere else. The first segment starts at its own node's
     centre and the last one stops at its own, which is what the
     horizontal rail does at 12.5% and 87.5%. */
  .sw-hero-simple .sw-hero-rail::before{display:none}
  .sw-hero-rail > button{position:relative}
  .sw-hero-rail > button::before{
    content:"";position:absolute;left:6px;top:0;bottom:0;width:1px;
    background:rgba(246,241,234,.2);
  }
  .sw-hero-rail > button:first-of-type::before{top:50%}
  .sw-hero-rail > button:last-of-type::before{bottom:50%}
  /* the node has to sit on top of the segment, not under it */
  .sw-hero-rail > button s{position:relative;z-index:1}

  /* THE TAB STRIP SAYS IT SCROLLS.
     It already scrolled -- overflow:auto -- but it cut off mid-word with
     no edge treatment, which reads as broken layout rather than as more
     content. A fade at the trailing edge is the difference. */
  .swa-nav{
    -webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 26px),transparent);
    mask-image:linear-gradient(90deg,#000 calc(100% - 26px),transparent);
  }
  .swa-nav::-webkit-scrollbar{display:none}
}


/* ======================================================================
   THE RAIL, CORRECTED

   Measured, not guessed: every node's centre sits at 25.5px from the top
   of the rail, and the line was drawn at 22px -- above the centre, so it
   crossed the upper third of all four circles instead of running through
   their middles. One variable now, used by the line, the spark and the
   cue, so the four of them cannot drift apart again.
   ====================================================================== */
.sw-hero-rail{--rail-y:25.5px}
.sw-hero-simple .sw-hero-rail::before,
.sw-hero-simple .sw-hero-rail::after{top:var(--rail-y)}
.sw-hero-rail .swa-spark{top:var(--rail-y)}
/* translate(-50%,-100%) with a 5px lift: the group's bottom edge lands
   just above the line instead of straddling it. */
.swa-cue{top:calc(var(--rail-y) - 5px);transform:translate(-50%,-100%)}

/* AND THE NODE PAINTS OVER THE LINE.

   The node is already opaque and already position:relative, but so is
   the line, and two positioned boxes with z-index:auto paint in tree
   order -- which put the line and the node in a coin toss that the line
   kept winning. Stated instead of assumed. */
.sw-hero-rail > button > s{z-index:1}

/* -------------------------------------------------- the cue sits on top
   It rested ON the line, which meant the line ran through the middle of
   the words. It sits on top of the line now -- the whole group, text and
   chevrons together -- so the line passes underneath it unbroken.

   Which also means there is nothing left to break the line FOR: the gap
   and the script that measured it are both gone, and the two segments
   simply meet in the middle. */
.sw-hero-simple .sw-hero-rail::before{right:50%}
.sw-hero-simple .sw-hero-rail::after{left:50%}

/* Smaller, with the chevrons just outside the words rather than spaced
   away from them. */
.swa-cue{padding:0 30px}
.swa-cue span{font-size:12px;letter-spacing:.03em;padding:0}
.swa-cue button{
  position:absolute;top:50%;transform:translateY(-50%);
  font-size:15px;padding:4px 6px;line-height:1;
}
.swa-cue button:first-child{left:4px}
.swa-cue button:last-child{right:4px}
.swa-cue.is-nudge button:first-child{transform:translateY(-50%) translateX(-3px)}
.swa-cue.is-nudge button:last-child{transform:translateY(-50%) translateX(3px)}
@media(prefers-reduced-motion:reduce){
  .swa-cue.is-nudge button:first-child,
  .swa-cue.is-nudge button:last-child{transform:translateY(-50%)}
}

/* ------------------------------------------------------- the subtext sits
   inside the spine rather than matching it edge for edge. Level with it,
   the caption read as another full-width band and the rail stopped
   looking like the thing above it. */
.swa-capwrap{max-width:920px}
.swa-cap{max-width:none}

/* ------------------------------------------------- air under the button */
.sw-hero-simple{padding-bottom:78px}
.swa-actions{padding-bottom:0}
@media(max-width:760px){
  .sw-hero-simple{padding-bottom:56px}
  /* the gap is measured on the desktop rail; stood up there is no gap */
  .sw-hero-simple .sw-hero-rail::before{right:auto}
}


/* ======================================================================
   THE ORG CHART, AS AN ACTUAL TREE

   Every connector is drawn from its own node's centre outwards, so
   there is no second coordinate system to fall out of step with the
   first. Each child draws a half-bar towards its siblings and a stub
   down to itself; put side by side those half-bars make the crossbar,
   and the crossbar is exactly as wide as the children are, whatever
   they contain and whatever the canvas is doing.
   ====================================================================== */
.swa-canvas{
  /* it is as tall as the tree now, not a fixed 300px box the tree had
     to be squeezed into */
  position:relative;height:auto;min-width:0;padding:16px 14px 18px;
  display:block;
  background-image:radial-gradient(rgba(246,241,234,.055) 1px,transparent 1px);
  background-size:17px 17px;
}
.swa-tree,.swa-tree ul{list-style:none;margin:0;padding:0}
/* width:max-content with auto margins, NOT a centring flex container.
   A flex parent centring an overflowing child clips it at BOTH ends and
   the scroll cannot reach the left one -- which is how the chart lost
   its first column and its last at the same time. Auto margins clamp to
   zero instead, so it scrolls from the left like anything else. */
.swa-tree{display:flex;justify-content:center;width:max-content;margin:0 auto}
.swa-tree ul{display:flex;justify-content:center;padding-top:16px;position:relative}
/* the stub down from a parent to its children's crossbar */
.swa-tree ul::before{
  content:"";position:absolute;top:0;left:50%;
  width:1px;height:16px;background:rgba(246,241,234,.2);
}
.swa-tree li{
  position:relative;padding:16px 6px 0;
  display:flex;flex-direction:column;align-items:center;
}
/* the crossbar, in halves: one reaching left from this child's centre,
   one reaching right, plus the stub down to the child itself */
.swa-tree li::before,
.swa-tree li::after{
  content:"";position:absolute;top:0;right:50%;
  width:50%;height:16px;
  border-top:1px solid rgba(246,241,234,.2);
}
.swa-tree li::after{right:auto;left:50%;border-left:1px solid rgba(246,241,234,.2)}
/* nothing reaches past the outermost children... */
.swa-tree li:first-child::before,
.swa-tree li:last-child::after{border:0}
/* ...but the last child still needs its stub, which its ::after just
   gave up, so its ::before grows the vertical edge instead */
.swa-tree li:last-child::before{border-right:1px solid rgba(246,241,234,.2)}
/* the root has no parent to connect to */
.swa-tree > li{padding-top:0}
.swa-tree > li::before,
.swa-tree > li::after{display:none}

.swa-seat{
  /* 132, not 150: five leaves plus their gaps have to fit the card at
     1440 or the chart scrolls in a hero, which nobody does. */
  position:static;transform:none;width:140px;box-sizing:border-box;
  padding:8px 9px 7px;border-radius:7px;
  border:1px solid rgba(246,241,234,.11);background:#191617;
}
/* the duty line is one line -- a seat that wrapped to two made its whole
   row look misaligned against the ones that did not */
.swa-seat > em{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.swa-zoom{top:10px;right:12px}

/* ======================================================================
   ONE BUTTON, TWO PLACES

   "run a test meeting" and "book a planning session" sit in the same
   slot -- the top right of a view header -- on two different screens,
   so they were two designs doing one job: a rounded filled pill against
   a square outlined link. Same component now, square like the rest of
   the site, and both of them pulse.

   They keep their own colours because they are not the same offer: the
   slate one is the app's own action, the clay one is the site's.
   ====================================================================== */
.swa-run,
.swa-planlink{
  display:inline-flex;align-items:center;gap:7px;white-space:nowrap;
  font:inherit;font-size:var(--ui-head);font-weight:700;line-height:1;
  padding:8px 15px;border-radius:0;border:1px solid transparent;
  text-decoration:none;cursor:pointer;
  transition:background .2s ease,color .2s ease,border-color .2s ease;
}
.swa-run{background:var(--swa-app-accent);color:#12100F}
.swa-run:hover{background:#CFDCE8}
.swa-planlink{background:var(--sw-accent);color:#171413}
.swa-planlink:hover{background:#E4BCAC;color:#171413}
.swa-planlink em{font-style:normal;transition:transform .2s ease}
.swa-planlink:hover em{transform:translateX(3px)}
.swa-run.is-live{
  background:rgba(169,184,198,.16);color:var(--swa-app-accent);
  border-color:rgba(169,184,198,.55);
}
/* the ring, square with them, and it does not stop after the first
   press any more -- it is the one thing in a still picture that says
   the picture is not still */
.swa-run-wrap{position:relative;display:inline-flex}
.swa-run-wrap[hidden]{display:none}
/* Only the run button pulses. The ring is there to say "press this to
   watch it work" -- the planning session is an ordinary offer, and a
   second thing flashing in the same window turns the first one into
   noise. */
.swa-run-wrap::after{
  content:"";position:absolute;inset:-4px;border-radius:0;
  opacity:0;pointer-events:none;
  border:1px solid var(--swa-app-accent);
  animation:swa-ping 3s ease-out infinite;
}
@media(prefers-reduced-motion:reduce){
  .swa-run-wrap::after{animation:none}
}

/* the offer reads as a sentence with a button on the end of it */
.swa-planoffer{display:inline-flex;align-items:center;gap:11px}
.swa-planask{
  font-size:var(--ui-meta);color:rgba(246,241,234,.55);white-space:nowrap;
}

/* ======================================================================
   THE DISCLAIMER IS THE WINDOW'S OWN FOOTER
   On the mockup, as asked, and still directly above the button it is
   the reason for -- so it reads as the app being honest about itself
   rather than as the page apologising for the app.
   ====================================================================== */
.swa-app > .swa-disclaimer{
  margin:0;padding:9px 14px;
  border-top:1px solid rgba(246,241,234,.08);
  background:#131011;
  font-size:var(--ui-meta);line-height:1.4;
  color:rgba(246,241,234,.49);text-align:left;
}
.swa-app > .swa-disclaimer::after{display:none}
.swa-actions{margin-top:18px}


/* The first pass at this section styled .swx-fit-item, which no longer
   exists -- but it ALSO set .swx-fit-grid and .swx-fit-top, which do,
   and it was quietly fighting the rules further down the file. Its
   border-top is where the rule between the paragraph and the columns
   was coming from. Removed rather than overridden: dead CSS that still
   matches live selectors is worse than dead CSS.

   The origin story, deliberately the smallest thing in the section.
   `.swx .swx-aside`, not `.swx-aside`: it is a <p>, and `.swx p` sets
   max-width:62ch at 0,1,1 -- so a bare class rule at 0,1,0 lost, and
   the rule under it stopped a third of the way across.

   No rule above it either. The two hairlines were fencing the columns
   in from both sides, and the columns already have three of their own. */
.swx .swx-aside{
  margin-top:34px;max-width:none;
  font-size:13px;color:rgba(246,241,234,.42);
}
.swx-steplink em{font-style:normal}
.swx-ctas--left{justify-content:flex-start;margin-top:34px}
.sw-custom-cta.swx-ctas{display:flex;margin-top:22px}

@media(max-width:900px){
  .swx{padding:76px 0}
}


/* ======================================================================
   NO FORCED FORMULA TAKES THE HOME PAGE'S SHAPE

   Same device as "what it takes to start": a header block, then three
   full-bleed columns divided by hairlines, each one label / heading /
   copy / a line on the baseline. The two pages are meant to read as one
   site, so where they are making the same kind of argument they should
   look like it.

   On the darker ground, which also gives the band either side of it an
   edge without needing a border.
   ====================================================================== */
.swx-fit{background-color:var(--sw-ground-dark)}
/* NO MEASURE ON EITHER, which is what home does and for the reason its
   own comment gives: the 74ch cap was what broke that subtitle onto two
   lines, and both of these fit the column easily at their size. They
   run inset to inset like everything else in this band. */
.swx-fit-top{max-width:none}
.swx-fit-top h2{max-width:none}
.swx .swx-fit-top p{max-width:none;margin:18px 0 0}
.swx-fit-top .swx-eyebrow{margin-bottom:0}
.swx-fit-top h2{margin-bottom:0}

.swx-fit-grid{
  /* THE HOME PAGE'S ARITHMETIC, WITH ITS VARIABLE, NOT A LOOKALIKE.

     Full bleed: the hairlines reach the page edges while the outer two
     columns carry --hx-inset as padding, so their text still lines up
     with the heading above and with every other left edge on the site.
     The middle column is a plain third of what is left, and the outer
     two are each a third plus the difference between the inset and a
     column's own padding.

     max(0px, ...) because the formula assumes the inset is wider than
     that 40px padding, and below 1025px --hx-inset drops to the 32px
     gutter -- at which point this would go negative and make the outer
     columns NARROWER than the middle, the exact inverse of the point.
     Floored at zero it falls back to equal thirds, which is right when
     there is no inset to compensate for. */
  --fit-d:max(0px, calc(var(--hx-inset) - 40px));
  --fit-mid:calc((100% - 2 * var(--fit-d)) / 3);
  display:grid;
  grid-template-columns:
    calc(var(--fit-mid) + var(--fit-d))
    var(--fit-mid)
    calc(var(--fit-mid) + var(--fit-d));
  margin-top:24px;
}
.swx-fit-col{
  display:flex;flex-direction:column;
  padding:40px;text-decoration:none;color:inherit;
  transition:background .2s ease;
}
.swx-fit-col + .swx-fit-col{border-left:1px solid rgba(246,241,234,.1)}
.swx-fit-col:first-child{padding-left:var(--hx-inset)}
.swx-fit-col:last-child{padding-right:var(--hx-inset)}
a.swx-fit-col:hover{background:rgba(246,241,234,.028)}

.swx-fit-label{
  display:block;margin-bottom:12px;
  font-family:'Questrial',sans-serif;
  font-size:12px;font-weight:700;letter-spacing:.17em;text-transform:uppercase;
  color:var(--sw-accent);
}
.swx-fit-col h3{
  margin:0 0 14px;font-family:'League Spartan',sans-serif;font-weight:700;
  font-size:clamp(20px,1.65vw,24px);line-height:1.06;letter-spacing:-.03em;
  text-transform:lowercase;color:#F6F1EA;
}
.swx .swx-fit-col p{
  margin:0 0 22px;max-width:none;
  font-size:15px;line-height:1.55;color:rgba(246,241,234,.68);
}
/* margin-top:auto, so the three foot lines land on one baseline however
   long the copy above them runs. */
.swx-fit-foot{
  display:inline-flex;align-items:center;gap:9px;
  margin-top:auto;padding-top:20px;
  border-top:1px solid rgba(246,241,234,.1);width:100%;
  font-size:12px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:rgba(246,241,234,.62);
  /* 16px, to match the arrow. margin-top:auto aligns the BOTTOM of each
     foot, so the rule at its top only lands level if all three are the
     same height -- and the one with an SVG in it was 3px taller than the
     two without, which put its rule 3px up from the other two. The whole
     point of this row is that those three rules agree. */
  line-height:16px;
}
a.swx-fit-col .swx-fit-foot{color:var(--n12-cream,#F6F1EA)}
.swx-fit-foot svg{width:16px;height:16px;transition:transform .2s ease}
a.swx-fit-col:hover .swx-fit-foot svg{transform:translateX(4px)}
.swx-fit .swx-aside{margin-top:34px}

@media(max-width:900px){
  .swx-fit-grid{grid-template-columns:1fr;margin-top:26px}
  .swx-fit-col{padding:26px 24px}
  .swx-fit-col:first-child{padding-left:24px}
  .swx-fit-col:last-child{padding-right:24px}
  .swx-fit-col + .swx-fit-col{border-left:0;border-top:1px solid rgba(246,241,234,.1)}
  /* THE RULE ABOVE THE FOOT GOES ON A PHONE.

     On a desktop it is doing real work: three columns side by side, and
     the rule is what makes their feet read as one row. Stacked, there is
     no row -- each column already has a divider above it from the rule
     directly above this one, so the foot's own border lands a second
     hairline a few lines below the first and the section reads as six
     dividers instead of three.

     Home's equivalent has none: .st-col stacks with one divider per
     column and the link simply sits under the copy. Same here now.

     padding-top drops with it. Twenty pixels of air existed to hold the
     copy off the rule; with no rule it is just a gap. 6 keeps the link
     from touching the paragraph above it. */
  /* No gap between the copy and the CTA. margin-top:auto was pushing the
     foot to the bottom of the column, which is what aligns three feet on
     one row side by side -- stacked there is no row to align to, so all
     it did was open a space under each paragraph. The link sits directly
     under the sentence it belongs to. */
  .swx-fit-foot{margin-top:0;border-top:0;padding-top:0;width:auto}
  /* `.swx .swx-fit-col p` at line 1457 is two classes and beats a bare
     `.swx-fit-col p`, so the first attempt at closing this gap measured
     22px when it should have been 10 -- the margin it was setting never
     applied. Matched specificity, and 6px is what is left between the
     sentence and the link it belongs to. */
  .swx .swx-fit-col p{margin-bottom:6px}
}

/* ======================================================================
   THE PLANNING OFFER STACKS, AND THE BUTTON IS A TEXT LINK

   The site's secondary CTA -- no fill, a hairline under it, an arrow
   that slides -- which is what home and planning both use for the
   quieter of two asks. At the app's own type size, because a 16px
   control inside a picture of an application is not a control in it.
   ====================================================================== */
.swa-planoffer{
  display:inline-flex;flex-direction:column;align-items:flex-end;gap:7px;
}
.swa-planask{
  font-size:var(--ui-meta);color:rgba(246,241,234,.55);white-space:nowrap;
}
.swa-planlink{
  display:inline-flex;align-items:center;gap:8px;white-space:nowrap;
  font-family:'Questrial',sans-serif;
  font-size:var(--ui-head);font-weight:400;line-height:normal;
  /* CLAY, because both of these leave the page -- one to /planning, one
     to /ideas -- which is exactly what the site's tertiary tier is for.
     They live inside the mockup rather than in the page's own copy, so
     they cannot join cta-n12.css's selector list, but they take its
     colour and its .32 hairline so the rule reads the same wherever it
     is met. */
  padding:0 0 2px;border:0;border-bottom:1px solid rgba(178,132,121,.32);
  border-radius:0;background:none;color:#B28479;
  text-decoration:none;
  transition:color .16s ease,border-color .16s ease;
}
.swa-planlink:hover{background:none;color:#C99084;border-bottom-color:#C99084}
.swa-planlink em{font-style:normal;transition:transform .18s ease}
.swa-planlink:hover em{transform:translateX(4px)}

/* ======================================================================
   THE FOOT OF THE HERO
   The note is centred in the window's footer strip, and there is real
   air between the window and the button under it -- they were close
   enough to read as one block.
   ====================================================================== */
.swa-app > .swa-disclaimer{text-align:center}
.swa-actions{margin-top:38px}
@media(max-width:760px){.swa-actions{margin-top:28px}}


/* ======================================================================
   GOALS CARRY HOW FAR ALONG THEY ARE

   A bar and a number next to the status. "on track" on its own is
   somebody's opinion; 70% is a position. The two say different things --
   how far, and whether that is far enough by now -- which is why the
   pill stays.
   ====================================================================== */
.swa-own--goal{grid-template-columns:22px minmax(0,1fr) 54px 30px auto;gap:9px}
.swa-prog{
  text-decoration:none;display:block;height:3px;border-radius:999px;
  background:rgba(246,241,234,.12);overflow:hidden;
}
.swa-prog s{
  display:block;height:100%;text-decoration:none;
  background:var(--swa-app-accent);border-radius:999px;
}
.swa-pct{
  font-size:var(--ui-meta);color:rgba(246,241,234,.5);
  text-align:right;font-variant-numeric:tabular-nums;
}

/* ======================================================================
   THE WRAP UP

   The meeting used to end by revealing one line on the to-dos screen,
   which is a small answer to "what did that achieve?". This is the
   answer: what got settled, what everyone leaves holding, and the
   counts underneath. It is also the pane the clock lands on, so the
   demonstration ends on the point rather than on a timer running out.
   ====================================================================== */
.swa-recap{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:0;border-bottom:1px solid rgba(246,241,234,.07);
}
.swa-recap-col{padding:11px 14px}
.swa-recap-col + .swa-recap-col{border-left:1px solid rgba(246,241,234,.07)}
.swa-recap-col > span{
  display:block;margin-bottom:9px;
  font-size:var(--ui-micro);font-weight:700;letter-spacing:.12em;
  text-transform:uppercase;color:rgba(246,241,234,.4);
}
.swa-recap-col p{
  margin:0 0 9px;font-size:var(--ui-meta);line-height:1.5;
  color:rgba(246,241,234,.55);
}
.swa-recap-col p:last-child{margin-bottom:0}
.swa-recap-col p b{
  display:block;font-weight:400;font-size:var(--ui-body);
  color:rgba(246,241,234,.86);margin-bottom:2px;
}
.swa-recap-col .swa-row{grid-template-columns:15px minmax(0,1fr) auto auto;padding:6px 0}
.swa-recap-col .swa-row:last-child{border-bottom:0}

.swa-recap-foot{
  display:flex;flex-wrap:wrap;align-items:center;gap:8px 18px;
  padding:10px 14px;font-size:var(--ui-meta);color:rgba(246,241,234,.5);
}
.swa-recap-foot b{color:#F6F1EA;font-weight:700}
.swa-recap-rate{margin-left:auto}
.swa-recap-rate b{color:var(--swa-app-accent)}

@media(max-width:640px){
  .swa-recap{grid-template-columns:1fr}
  .swa-recap-col + .swa-recap-col{border-left:0;border-top:1px solid rgba(246,241,234,.07)}
  .swa-recap-rate{margin-left:0}
}


/* The first column's two ways in, on the baseline where the other two
   columns carry their closing line. Links, not buttons: a pair of
   filled buttons would be taller than a 16px line of text and push this
   column's rule out of line with the other two, which is the one thing
   this row is built to get right. */
/* COLUMN GAP 26, not 0. It was gap:0 with only a row-gap set, so the
   two links had nothing holding them apart on a shared line -- at 1440
   the row's justification did it by accident, and anywhere narrower they
   ran into each other. 26 is the gap every other CTA pair on the site
   uses. */
.swx-fit-foot--links{gap:6px 26px;flex-wrap:wrap}
/* NOT THE LABEL TREATMENT. The foot row is 12px uppercase bold because
   that is home's .st-cost -- a fact line, the thing that makes three
   cards read as one row. These two are links, and wearing a fact's
   clothes made them look like labels that happened to be underlined.

   Home keeps the two apart in the same card: .st-cost bold uppercase,
   .st-more regular and sentence case. Same here. line-height stays 16px
   so the three feet are still the same height and their rules agree. */
.swx-fit-foot--links a{
  /* 16 and .78, which is the site's secondary CTA -- .n12-help, .st-link,
     .cl-link, .pl-btn-text and .sw-btn--text are all 16px at .78. These
     were 14px at full cream, so beside the footer's secondary they read
     both smaller and brighter. Two differences, both of them accidents of
     this rule predating the tier system. */
  font-size:16px;font-weight:400;letter-spacing:.01em;text-transform:none;
  color:rgba(246,241,234,.78);
  /* A BORDER AGAIN, AND THE REASON IT CAN BE ONE NOW.

     This was text-decoration on purpose: a border plus its padding adds
     3px to the line box, and back then only TWO of the three feet were
     links -- the third was the plain "$500 once" line -- so the two with
     borders came out 19px against its 16 and their rules sat 3px high.

     All three are links with arrows now, so whatever the border adds it
     adds to all three equally and they stay level. And a border is what
     she actually wants: text-decoration underlines TEXT only, so the
     arrow sat off the end of the line with nothing under it. */
  text-decoration:none;
  border-bottom:1px solid rgba(246,241,234,.3);
  padding-bottom:2px;
  transition:color .16s ease,border-color .16s ease;
}
.swx-fit-foot--links a:hover{color:var(--n12-cream,#F6F1EA);border-bottom-color:var(--n12-cream,#F6F1EA)}
.swx-fit-foot--links i{
  font-style:normal;padding:0 10px;color:rgba(246,241,234,.35);
}


/* Status first, then how far along. The pill answers "is this where it
   should be by now?" and the number answers "how far is it?" -- and she
   wants the judgement before the measurement. The bar stays next to the
   number it belongs to rather than being stranded on the other side of
   the pill. */
/* 80px, not auto. An auto column is sized by its own row's content, so
   "not started" started 27px left of "on track" and the pills were
   right-aligned as a group when they read as a column of labels that
   should start together. justify-self:start alone could not fix it --
   it positions within the cell, and the cell was the wrong width. */
.swa-own--goal{grid-template-columns:22px minmax(0,1fr) 80px 54px 34px}
.swa-own--goal .swa-pill{justify-self:start}


/* the divider between the two groups of goals */
.swa-goallabel{
  display:block;padding:9px 12px 6px;
  font-size:var(--ui-micro);font-weight:700;letter-spacing:.12em;
  text-transform:uppercase;color:rgba(246,241,234,.38);
}
.swa-card > .swa-goallabel + .swa-own{border-top:0}
.swa-own + .swa-goallabel{
  margin-top:2px;border-top:1px solid rgba(246,241,234,.07);
}
/* No avatar column: a company goal is not anybody's, and the missing
   face is what separates the two groups without a second heading. */
.swa-own--co{grid-template-columns:minmax(0,1fr) 80px 54px 34px}


/* ======================================================================
   THE LINE SITS AT THE NODE'S CENTRE BY CONSTRUCTION

   With the numerals gone the node is the first thing in the button, so
   its centre is exactly half its own height. Derived from one size
   variable rather than measured and hard-coded: --rail-y was 25.5px
   because that is where the numerals happened to push the node, and a
   number like that is wrong the moment anything above it changes.

   Now the node, the travelling light and the line all read the same
   variable, so changing the node size moves all three together.
   ====================================================================== */
.sw-hero-rail{--node:13px;--rail-y:calc(var(--node) / 2)}
.sw-hero-rail > button > s,
.sw-hero-rail .swa-spark{width:var(--node);height:var(--node)}
/* the label had 13px of air under a numeral that is no longer there */
.sw-hero-rail b{margin-top:11px}


/* ======================================================================
   WHAT IT COSTS GETS THE GROUND

   First light, where the hero is dusk, so the page moves through the day
   as you scroll instead of showing the same desert twice.

   Flat scrim with hard edges, which is what the home page's start band
   does and for the same reason: the picture begins and ends at the
   section's own boundary, so it reads as a deliberate inset rather than
   something bleeding through the page.

   It can sit this open -- .70 rather than the hero's two-layer wash --
   because the frame has no hotspot in it. No sun, no bright horizon
   band, and the middle third where the headline sits is empty sky.
   ====================================================================== */
/* This band has had a photograph, then not, then one again. The live
   rules are at the foot of this file; the two intermediate versions are
   deleted rather than left to fight it -- the display:none from the
   middle one was beating the current block and the band was rendering
   flat while every declaration said otherwise. */


/* ======================================================================
   NO FORCED FORMULA: ARGUMENT LEFT, WAYS IN RIGHT

   The three are alternatives, not features. A vertical list reads as
   "pick one"; three columns read as "compare these across the same
   rows", which is the wrong promise about three things that are not
   comparable line for line.
   ====================================================================== */
.swx-split{
  display:grid;grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr);
  gap:64px;align-items:start;padding:0 var(--hx-inset);
}
.swx-split-copy h2{margin:0 0 18px;max-width:none}
.swx .swx-split-copy p{margin:0;max-width:none}
.swx-split-copy .swx-eyebrow{margin-bottom:0}
.swx-split-copy .swx-ctas{margin-top:30px}

.swx-opts{display:flex;flex-direction:column}
.swx-opt{
  display:grid;grid-template-columns:auto minmax(0,1fr);gap:20px;
  padding:20px 0;border-top:1px solid rgba(246,241,234,.12);
}
.swx-opt:last-child{border-bottom:1px solid rgba(246,241,234,.12)}
.swx-opt > i{
  font-style:normal;font-family:'League Spartan',sans-serif;font-weight:700;
  font-size:12px;letter-spacing:.14em;color:var(--sw-accent);padding-top:4px;
}
.swx-opt b{
  display:block;font-family:'League Spartan',sans-serif;font-weight:700;
  font-size:19px;line-height:1.1;letter-spacing:-.02em;
  text-transform:lowercase;color:#F6F1EA;margin-bottom:6px;
}
.swx .swx-opt p{margin:0;max-width:none;font-size:14.5px;line-height:1.55;color:rgba(246,241,234,.66)}
.swx-opt em{
  display:block;margin-top:7px;font-style:normal;
  font-size:12px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:rgba(246,241,234,.42);
}

/* ======================================================================
   THE PARTS WE BUILD FOR YOU

   Two panels, so these read as two offers rather than two facts.

   No photograph. It carried one for a while and the rules for it are
   gone rather than switched off, so when the new image arrives it goes
   in here clean instead of on top of three dead layers.
   ====================================================================== */
.swx-build > .swx-wrap{position:relative;z-index:1}
/* .swx h2 caps at 18ch, which broke this one after "build for" and left
   "you." alone on a line. It fits the column easily unconstrained. */
.swx-build h2{max-width:none}

/* the month-to-month line under the price headline. It answers the last
   purchasing question the page leaves open, so it sits with the price
   rather than in the small print. */
.swx-price-note{
  margin:14px 0 0;
  font-family:'Questrial',sans-serif;
  font-size:14.5px;line-height:1.6;color:rgba(246,241,234,.58);
}

.swx-build-panels{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:24px;margin-top:32px;
}
.swx-panel{
  display:flex;flex-direction:column;
  padding:34px;border:1px solid rgba(246,241,234,.14);
  background:rgba(23,20,19,.92);
}
.swx-panel > span{
  display:block;margin-bottom:14px;font-family:'Questrial',sans-serif;
  font-size:12px;font-weight:700;letter-spacing:.17em;text-transform:uppercase;
  color:var(--sw-accent);
}
.swx-panel h3{
  margin:0 0 12px;font-family:'League Spartan',sans-serif;font-weight:700;
  font-size:clamp(22px,2vw,28px);line-height:1.06;letter-spacing:-.03em;
  text-transform:lowercase;color:#F6F1EA;
}
/* 1.6 and .68, which is the site's body token: home's .hx-sub and
   planning's .pl-sub both compute to 15px/24 at rgba(246,241,234,.68).
   This ran 1.58 and .7 -- close enough to look deliberate and not be. */
.swx .swx-panel p{margin:0 0 24px;max-width:none;font-size:15px;line-height:1.6;color:rgba(246,241,234,.68)}
.swx-panel .swx-build-link{margin-top:auto;align-self:flex-start}
/* COLOUR AND UNDERLINE NOW COME FROM cta-n12.css, which owns the site's
   three CTA tiers. Both of these links leave the page -- one to /contact,
   one to /ideas -- so they are tertiary and clay, not cream.

   The declarations that set colour, size, underline and padding are gone
   from here rather than overridden there, because this file loads AFTER
   cta-n12.css and would have silently won. That is the fault this page
   has already hit four times: a retired declaration still matching a live
   selector, every value reading correct and the page rendering wrong.

   What stays is the only part that is genuinely this layout's business --
   where the link sits in its panel. */
.swx-build-link{white-space:nowrap;margin-top:6px}

@media(max-width:900px){
  .swx-split{grid-template-columns:1fr;gap:34px}
  .swx-build-panels{grid-template-columns:1fr;gap:16px}
  .swx-panel{padding:26px 24px}
}


/* ======================================================================
   THE RAIL IS A TAB STRIP

   The dots on a thin line read as a progress indicator -- something
   showing you where you are, not something you press. And the hit area
   was a 13px circle.

   Underlined tabs, which is the device the application underneath it
   already uses for Home / Meetings / Business Plan. The hero's control
   and the product's control are now the same object rather than two
   different ideas stacked on each other.

   The whole cell is the button, so the click target is the tab and not
   the word in the middle of it.
   ====================================================================== */
.sw-hero-simple .sw-hero-rail::before,
.sw-hero-simple .sw-hero-rail::after{display:none}
.sw-hero-rail > button > s{display:none}

.sw-hero-rail{
  display:grid;grid-template-columns:repeat(4,1fr);gap:0;
  width:min(100%,1060px);margin:0 auto;
  border-bottom:1px solid rgba(246,241,234,.16);
}
.sw-hero-rail > button{
  display:block;width:100%;position:relative;
  padding:16px 12px 18px;border:0;background:none;cursor:pointer;
  color:rgba(246,241,234,.6);
  transition:background .2s ease,color .2s ease;
}
/* the underline, drawn on every tab and coloured only on the live one,
   so nothing moves when the selection changes */
.sw-hero-rail > button::after{
  content:"";position:absolute;left:0;right:0;bottom:-1px;height:2px;
  background:transparent;transition:background .2s ease;
}
.sw-hero-rail > button:hover{background:rgba(246,241,234,.06);color:#F6F1EA}
.sw-hero-rail > button:focus-visible{outline:2px solid #E4BCAC;outline-offset:-3px}
/* peach, the same peach as the underline: the label and its mark are
   one thing, and at 13px the darker clay was too quiet to carry it */
.sw-hero-rail > button[aria-selected="true"]{color:#E4BCAC}
.sw-hero-rail > button[aria-selected="true"]::after{background:#E4BCAC}
.sw-hero-rail b{
  display:block;margin:0;max-width:none;text-align:center;
  font-size:13px;letter-spacing:.1em;color:inherit;
}

/* the cue sits above the strip on its own line */
.swa-cue{
  position:relative;top:auto;left:auto;transform:none;
  grid-column:1/-1;order:-1;justify-self:center;
  margin:0 0 16px;padding:0;
}

@media(max-width:760px){
  /* THE FOUR TABS STACK.

     Four across was built and rendered -- they fit, at 10px on one line
     or 13px broken onto two -- and she read the row as messy at phone
     width. Stacked it is, which is also what software-n12.css has always
     done at this width, so this block now only carries the selected
     state and the type.

     The clay left bar rather than an underline: stacked, an underline
     under each row is four horizontal rules in a column, which is a
     list of dividers. A bar down the left edge marks one row without
     drawing anything the eye reads as a separator. */
  .sw-hero-rail{
    grid-template-columns:1fr;border-bottom:0;
    width:100%;max-width:340px;
  }
  .sw-hero-rail > button{
    padding:11px 14px;text-align:left;
    border-left:2px solid rgba(246,241,234,.14);
  }
  .sw-hero-rail > button::before,
  .sw-hero-rail > button::after{display:none}
  .sw-hero-rail > button[aria-selected="true"]{
    border-left-color:#B28479;background:rgba(246,241,234,.04);
  }
  .sw-hero-rail b{
    text-align:left;font-size:12px;letter-spacing:.06em;
    white-space:nowrap;
  }
  /* THE RAIL'S OWN LINE GOES.

     .sw-hero-rail::after paints a 1px strip at top:6.5px in cream at
     .2 -- the horizontal spine from the original design, when the four
     nodes sat ON a line. There are no nodes any more and the tabs carry
     their own underline, so this is a second rule floating above them
     with nothing attached to it. The desktop rules already hide both
     pseudo-elements; the phone block never did. */
  .sw-hero-simple .sw-hero-rail::before,
  .sw-hero-simple .sw-hero-rail::after,
  .sw-hero-rail::before,
  .sw-hero-rail::after{display:none}

  /* THE WINDOW STOPS JUMPING.

     Measured at 390, the app body by view: plan 611, meetings 590,
     dashboard 614, org 393 -- and the meeting while it plays runs
     590 -> 547 -> 692 -> 569 -> 476 -> 657 as rows go live and the
     wrap-up appears. Every one of those is the page reflowing under
     whatever you were reading.

     692 is the tallest state anywhere, so that is the floor. The org
     view will sit in a taller box than it needs; a fixed frame with air
     in it is what an app window looks like, and it is the price of the
     page holding still. */
  .swa-app-body{min-height:692px}

  /* The caption's line break goes. It is written for a desktop measure,
     where it splits the sentence at a sensible place; at 390 the text
     already wraps five times and the extra break just adds a sixth line
     of hero to scroll past. */
  .swa-cap br{display:none}

  /* THE HEADLINE LANDS ON TWO LINES.

     38px gives three at 390 and a 116px block. Counted by painted line
     rects rather than by dividing height by line-height -- the first
     attempt at this read font-size off a live computed-style object
     AFTER changing it, so every size came back the same and the answer
     was nonsense.

     36 is the largest that gives two. 34 gives the same two lines with
     room to spare on a 360px phone, and a 69px block against 116.

     40px NOW, to match the planning page -- measured, its h1 is 40/40.8
     at this width. This headline is longer than "stop winging it." so at
     40 it goes back to three lines and about 123px. Sent for her to look
     at; 34 is the value to come back to if the extra line is not worth
     the size. */
  .sw-hero-simple h1{font-size:var(--n12-h1)}

  /* Tested-with-real-teams reads left on a phone. Centred, its three
     lines of body each start at a different x and the eye has to find
     the beginning of every one; at this measure that costs more than
     the symmetry is worth. The desktop band stays centred. */
  .swx-proof{text-align:left}
  .swx-proof-link{margin-left:0;margin-right:auto}

  /* The two bands' washes come up on a phone as well -- declared at the
     very END of this file, not here, because their base rules sit around
     line 1990 and would win from there. See BOTH PHOTOGRAPHS COME UP ON
     A PHONE below. */

  /* 13.5, the phone size every other text CTA on the site runs.

     This is DOWN HERE rather than beside the other .swx-fit-foot phone
     rules for a reason worth recording: those sit in a media query
     around line 1370, and the base `.swx-fit-foot--links a{font-size:16px}`
     is at 1494 -- LATER in the same file. A media query adds no
     specificity, so the base rule won and the first attempt at this
     changed nothing while reading as though it should have. Placed
     after the rule it is overriding, it works. */
  .swx-fit-foot--links a{font-size:13.5px}
  .swx-fit-foot--links a svg{width:16px;height:14px}

  .swa-cue{margin-bottom:12px}
}


/* ======================================================================
   THE PROOF BAND
   One sentence, centred, with air around it. Questrial rather than
   League Spartan: it is a statement, not a heading, and the display
   face at this size would read as a slogan.
   ====================================================================== */
.swx-proof{background-color:var(--sw-ground)}
/* The centred one-sentence version of this band is gone. Its rules went
   with it rather than being overridden further down the file -- a third
   round of that today would be pushing my luck. */


/* ======================================================================
   EYEBROWS MATCH THE OTHER TWO PAGES

   .pl-eyebrow on planning, .st-eyebrow and .cl-eyebrow on home are all
   rgba(246,241,234,.7) -- a muted cream. This page was running peach for
   the same job, which is why its section heads read as a louder thing
   than theirs.

   Clay stays where home puts clay: on the column labels inside a band,
   not on the band's own eyebrow. .st-label is #B28479 and so are these.
   Two levels of label, two colours, same rule on every page.
   ====================================================================== */
.sw-hero-simple .eyebrow,
.swx-eyebrow{color:rgba(246,241,234,.7)}
.swx-fit-label,
.swx-panel > span{color:var(--sw-accent)}


/* ======================================================================
   THE PROOF BAND, IN THE SITE'S SHAPE
   Eyebrow, lowercase heading, supporting line -- home's .tr-lede, which
   is the same argument on the other page. Nothing centred, nothing in a
   face the rest of the page does not use.
   ====================================================================== */
/* Centred. It is the one band on the page with nothing beside it and
   nothing under it to line up with -- no columns, no panels, no button
   -- so the left edge was holding it to a grid it is not part of. */
/* 118, the rhythm every other band on all three pages runs. It was 96,
   which is the only band padding on the site that is not 118 and read as
   this section being slightly shallower than its neighbours for no
   reason anyone chose. */
.swx-proof{padding:118px 0;text-align:center}
.swx-proof h2{max-width:26ch;margin:0 auto 16px}
.swx-proof p{max-width:62ch;margin-inline:auto;font-size:15px;line-height:1.6;color:rgba(246,241,234,.68)}
@media(max-width:900px){.swx-proof{padding:70px 0}}

/* ======================================================================
   THE TABS SAY THEY ARE TABS WITHOUT BEING TOLD

   "pick a section" is gone, so the strip has to carry the affordance on
   its own. Three changes, none of them loud:

   The resting label was rgba(.6), which on a dark ground is the opacity
   a DISABLED control gets. At .78 they read as available.

   Hairlines between them, so four words become four cells. This is the
   one that does most of the work: unseparated, they read as a sentence.

   And every tab carries its underline at low opacity, not just the live
   one -- so the row reads as four slots with one filled, rather than a
   rule with a mark on it.
   ====================================================================== */
.sw-hero-rail > button{color:rgba(246,241,234,.78)}
.sw-hero-rail > button + button{box-shadow:inset 1px 0 0 rgba(246,241,234,.12)}
.sw-hero-rail > button::after{background:rgba(246,241,234,.14)}
.sw-hero-rail > button:hover{background:rgba(246,241,234,.07);color:#F6F1EA}
.sw-hero-rail > button:hover::after{background:rgba(246,241,234,.3)}
.sw-hero-rail > button[aria-selected="true"]::after{background:#E4BCAC}

@media(max-width:760px){
  /* stacked, so the dividers go horizontal and the underline is already
     a left bar */
  .sw-hero-rail > button + button{box-shadow:inset 0 1px 0 rgba(246,241,234,.12)}
}


/* The claim band's photograph lived here and has moved to the price
   band at the foot of this file. Deleted rather than suppressed, along
   with the add-ons band's display:none -- between them those two blocks
   were the reason the price band was rendering flat while every
   declaration in the live block said it should not. */
.swx-proof > .swx-wrap{position:relative;z-index:1}


/* ======================================================================
   THE GROUNDS, RESET

   Lighter (#171413) for the two bands that carry columns and panels --
   no forced formula and optional add-ons. Darker (#0F0D0C) for the one
   between them, so the centred claim sits in a dip rather than reading
   as a third band of the same colour.

   Every one of these is a plain colour declaration rather than an
   override of an override: the earlier rules for these sections set
   the opposite values, and the file already has more layers of that
   than it should.
   ====================================================================== */
.swx-fit{background-color:var(--sw-ground)}
.swx-build{background-color:var(--sw-ground)}
.swx-proof{background-color:var(--sw-ground-dark)}

/* ------------------------------------------------ the picture moves on
   The sunset comes off the claim band and goes behind the price, which
   is the last thing on the page. First light at the top, last light at
   the bottom, and the middle of the page is type on flat ground.

   The claim band's own picture rules are deleted above rather than
   switched off here, so nothing is left to suppress. */
.swx-price{position:relative;isolation:isolate;overflow:hidden}
.swx-price::before,
.swx-price::after{content:"";position:absolute;inset:0;z-index:0;pointer-events:none}
.swx-price::before{
  /* Blue hour now, at 78% -- her pick from four crops. It is 2880x1621
     and has height to spare in a band this short, which is the opposite
     of the hero's problem with the frame it traded away. */
  background:url("/assets/images/desert-blue-hour.webp") center 78%/cover no-repeat;
  background-image:image-set(url("/assets/images/desert-blue-hour.avif") type("image/avif"),url("/assets/images/desert-blue-hour.webp") type("image/webp"));
  /* onto the site grade, off the lone saturate(.7) */
  filter:saturate(.6) brightness(.74);
}
/* .78 rather than the .70 this band ran the first time it had a
   photograph: that was the dawn frame, which has no hotspot. This one
   has a bright horizon and the headline is 50px of cream sitting on it. */
.swx-price::after{background:rgba(15,13,12,.78)}
.swx-price > .swx-wrap{position:relative;z-index:1}


/* ======================================================================
   EYEBROW TO HEADING, MEASURED OFF THE PLANNING PAGE

   Planning runs two values and nothing else:

     section eyebrow over a 38px heading   margin-bottom 0
     card label over a 24px heading        margin-bottom 10

   The zero is not an oversight -- planning's own comment says the bands
   "run their eyebrow straight into the heading and let the heading's
   own line box do the spacing". A 38px heading on 39.5 leading already
   carries the air.

   This page was running 0, 12, 12 and 12 on the four section eyebrows
   -- three of them wrong and one right, which is worse than four wrong
   because it looks deliberate. And 12 and 14 on the labels where
   planning uses 10.
   ====================================================================== */
.swx-eyebrow{margin-bottom:0}
.swx-fit-label{margin-bottom:10px}
.swx-panel > span{margin-bottom:10px}
/* planning's hero eyebrow sits 12 off a 64px h1; this one is 56px */
.sw-hero-simple .swa-copy .eyebrow{margin-bottom:12px}

/* ======================================================================
   THE LIVE TAB IS CLAY, NOT PEACH

   She is right that peach is not really a site colour. Counted across
   assets/css: clay #B28479 appears 48 times and is spread over home's
   start band, the proof tree, planning and this page. Peach #E4BCAC
   appears 42 times -- but 38 of those are in this page's own two files
   and only 4 anywhere else, on one planning band. It is a habit this
   page picked up, not a colour the site owns.

   So the live tab and its underline are clay, and the other three go
   back to cream. Only the selected one is coloured.
   ====================================================================== */
.sw-hero-rail > button{color:rgba(246,241,234,.78)}
.sw-hero-rail > button:hover{color:#F6F1EA}
.sw-hero-rail > button::after{background:rgba(246,241,234,.14)}
.sw-hero-rail > button:hover::after{background:rgba(246,241,234,.3)}
.sw-hero-rail > button[aria-selected="true"]{color:var(--sw-accent)}
.sw-hero-rail > button[aria-selected="true"]::after{background:var(--sw-accent)}


/* ======================================================================
   TESTED WITH REAL TEAMS GETS THE MIDDAY FRAME

   The page now runs first light in the hero, hazy midday here and last
   light at the foot -- the middle of the day in the middle of the page.

   1983x793 is 2.5:1, which suits a 300px band far better than the 16:9
   frames: at 1440 wide it scales to 576 tall and the band shows the
   middle 52% of it rather than a thin slice. The horizon sits in that
   middle, which is why it survives the crop.

   The scrim is .60, measured rather than picked. The binding
   constraint is the 15px paragraph at .68 opacity, which needs 4.5:1 --
   the 38px heading is large text and only needs 3.

   Measured against the BRIGHTEST ground pixel behind the copy, not an
   average, because an average passes while the word sitting on the
   bright patch fails:

     .72  body 5.97:1
     .66  body 5.38:1
     .60  body 4.83:1   lightest that still clears 4.5
     .50  body 4.05:1   fails

   The blue-hour frame is far darker than the pale midday one it
   replaced, which is why this band can now run .60 where that one
   needed .72 and still showed less of itself.

   The paragraph stays at .68. Full cream would buy another two stops of
   scrim, but .68 is the site's supporting-copy tone -- .st-sub on home
   runs it -- and this band's body should not be brighter than every
   other band's just to show more photograph.
   ====================================================================== */
.swx-proof{position:relative;isolation:isolate;overflow:hidden}
.swx-proof::before,
.swx-proof::after{content:"";position:absolute;inset:0;z-index:0;pointer-events:none}
/* THE RED OVERHEAD FRAME, WHICH IS THE ONE THIS BAND SHOULD ALWAYS HAVE HAD.

   The blue overhead frame was chosen when the software page was meant to
   run cool throughout. It does not any more -- the hero carries the blue
   and the rest of the page sits in the site's red desert, which is what
   this frame is.

   Deliberately NOT put through the hero pipeline. That pipeline is built
   around a blueness mask separating sky from ground, and this is top-down
   with no sky in it: every pixel falls outside the mask and nothing would
   happen. It also gets no hue rotation, because rotating red sand is
   exactly what turned the hero's ground magenta.

   2880x1152 at 2.50:1, WebP q0.90, 519KB. Quality below that was tested
   and rejected -- q0.82 saves 200KB but jumps to 2.26 mean per-pixel
   difference, and this band is dense scrub texture where that shows.

   AND AVIF GETS UNDER THAT BAR WITHOUT PAYING FOR IT. What was never
   tried when the cheaper WebP was rejected was a different format.
   Measured against the shipping WebP on the same yardstick:

     AVIF crf 18   215 KB   2.09 mean per-pixel difference
     AVIF crf 22   180 KB   2.29
     AVIF crf 26   145 KB   2.56
     WebP q0.82    319 KB   2.26   <- rejected

   crf 18 is the one that is BETTER than the version already ruled out
   and still 304 KB lighter than what shipped. The WebP stays underneath
   as the fallback, so a browser without AVIF is exactly where it was.

   saturate(.6) brightness(.74) is the site grade, replacing the lone
   saturate(.72) this band used to run -- it was the last picture on the
   page still on its own treatment. */
.swx-proof::before{
  background:url("/assets/images/desert-overhead-red.webp") center center/cover no-repeat;
  background-image:image-set(
    url("/assets/images/desert-overhead-red.avif") type("image/avif"),
    url("/assets/images/desert-overhead-red.webp") type("image/webp"));
  background-position:center center;
  background-size:cover;
  background-repeat:no-repeat;
  filter:saturate(.6) brightness(.74);
}
.swx-proof::after{background:rgba(15,13,12,.60)}
/* The band is centred, so its link has to be too -- .n12-cta-3 is an
   inline-flex and would otherwise sit at the left edge of a centred
   block.

   No top margin: the paragraph above it already carries its own bottom
   margin, and 30px on top of that opened a gap twice the size of the one
   between the heading and the paragraph. */
.swx-proof-link{margin:0 auto}
.swx-proof > .swx-wrap{position:relative;z-index:1}


/* ======================================================================
   THE DISCLAIMER SPANS THE WINDOW

   It was already text-align:center and still sat in the left corner,
   because it kept max-width:54ch from when it was a standalone line
   under the app -- 297px inside a 1060px frame, centred within its own
   narrow box. Centring text does nothing if the box is not the width
   of the thing you are centring in.
   ====================================================================== */
.swa-app > .swa-disclaimer{max-width:none;width:100%}

/* ======================================================================
   THE HERO KEEPS ITS BLUE AND LOSES HALF ITS WASH

   The frame is the only cool image on the three pages and she wants it
   that way, so the job is to show more of it rather than to grade it
   warm.

   The limit was never the photograph. It was that the small text is
   cream at 70-78% opacity, and cream at .74 over a lightening ground
   runs out of contrast long before the picture does. Measured, both
   together:

     wash    current opacities          tabs+caption at full cream
             eyebrow tabs caption       eyebrow tabs caption
     x0.74    6.18  5.89  5.17           10.77  8.47  7.84
     x0.60    5.49  5.03  4.42            9.27  7.04  6.50
     x0.48    4.94  4.39  3.74            8.09  6.00  5.35
     x0.38    4.45  3.87  3.32            7.14  5.20  4.61

   At the current opacities the wash cannot pass x0.58 -- a 20% change,
   barely visible. With the tabs and caption at full strength it goes to
   x0.48, which is a third lighter again.

   So: x0.50, tabs and caption at full cream, and the filter back to
   saturate(.95) brightness(1) so the blue reads as its own colour
   rather than a muted version of it.

   The EYEBROW stays at .70. That value is planning's .pl-eyebrow and
   was matched on purpose two commits ago; at x0.50 it measures about
   4.9, so it does not need the help.
   ====================================================================== */
/* THE HERO TAKES THE TREATMENT EVERY OTHER PICTURE ON THE SITE HAS.

   It ran saturate(.95) brightness(1) -- effectively untreated -- while the
   planning video, the why-plans-fail band and the closing band all run
   saturate(.6) brightness(.74) hue-rotate(-18deg). That is why it read as
   the crispest, most colourful frame on the site: it was the only one not
   being graded in CSS at all.

   THE ROTATION CAME BACK OFF, AND WENT INTO THE FILE INSTEAD.

   hue-rotate(-18deg) is what turned the sand pinky purple. Measured, this
   frame's sand: 11deg untreated, 353deg with the rotation -- out of
   red-orange and into magenta. On planning's footage that rotation is a
   correction; on a frame whose ground is already this red it is an
   overshoot.

   It could not simply be deleted, because the same rotation is what holds
   the sky where she wants it: 217deg raw, 204deg rotated, 220deg without.
   A CSS filter has no way to treat the two halves of one picture
   differently.

   So the rotation now happens in the image, applied through the same
   blueness mask the desaturation uses, and CSS keeps only the two values
   that are meant to hit the whole frame. Sky stays at 204, sand returns
   to 10 -- within a degree of where the camera left it.

   Note this is NOT an opacity change, which is what was first asked for.
   The hero sits on #0F0D0C, so lowering opacity composites the picture
   toward the ground and makes it darker rather than quieter -- the
   opposite of the "lighten it" half of the same note. Saturation is what
   "crisp and colourful" actually names, so saturation is what moves.

   Measured, sky saturation 0.075 -> 0.036. And it happens to fix the hero
   contrast that the missing wash left open: the brightest pixel behind the
   tabs goes rgb(150,155,164) -> rgb(111,115,118), so the cream tabs move
   2.48 -> 4.26 and clear the 4.5 bar's neighbourhood without anything
   being laid over the photograph. */
.sw-hero-simple::before{filter:saturate(.6) brightness(.74)}

/* THE HERO'S BUTTON WAS UNDER THE PHOTOGRAPH, WHICH IS WHY IT LOOKED
   SHADOWED.

   ::before is position:absolute with z-index:0. In CSS painting order a
   POSITIONED element with z-index 0 paints in the final layer -- above
   block backgrounds and above inline text -- so anything in this hero
   that is not itself positioned with a z-index sits UNDER the picture.
   .swa-copy, .sw-hero-rail and .swa-stage all carry position:relative
   and z-index:2. .swa-actions carried neither.

   At opacity 1 the picture covered the button completely and the fault
   would have been obvious immediately. At .28 it only tints it, and a
   warm dusk frame over cream is indistinguishable from a soft shadow --
   which is exactly what she saw.

   Measured: the button's declared background is rgb(246,241,234) and it
   was painting rgb(166,162,158) at the top and rgb(204,200,194) at the
   bottom, the gradient being the sky-to-ground of the photograph itself.
   With this rule it paints rgb(246,241,234) at both corners. */
.swa-actions{position:relative;z-index:1}

/* AND THE FRAME DROPS TO 28%.

   Her call, made off the rendered ladder at 1, .65, .45 and .28 rather
   than off a description. What this does, so it is not mistaken later for
   a transparency effect: the hero's ground is #0F0D0C, so opacity here
   composites the picture toward near-black. It does not make the frame
   quieter against a neutral, it makes it darker. The photograph is still
   at full strength, there is just 72% less of it reaching the eye.

   The side effect is the hero's contrast problem closing on its own. Every
   piece of copy has been under threshold since the wash came off, and at
   this opacity the ground behind the tabs is dark enough that the cream
   clears 4.5 with room. Measured in the same pass and recorded below. */
.sw-hero-simple::before{opacity:.28}


/* ======================================================================
   THE FRAMES TRADE PLACES

   She compared them live and kept the dusk frame in the hero, so the two
   swap: dusk at the top, blue hour at the foot.

   THE DUSK FRAME IS RESAMPLED FOR THIS, not used as it was. It is
   1983x793 -- encoded for a 300px band -- and the hero is 1440x1160, so
   cover scales it to HEIGHT and it has to fill 2320 device pixels on a 2x
   screen. As the original JPEG that is a 2.93x upscale, which is worse
   than the stretch that made this hero look low-res a week ago.

   Resampled to 2880x1152 with high-quality smoothing and encoded WebP,
   the browser's remaining scale is 2.01x and the artifacts are smoothed
   during a good resample instead of magnified after a bad one. Measured
   against the source: roughness 0.479 -> 0.405, banding 69 -> 55 hard
   steps, at the same 88KB.

   It adds no detail -- nothing can. If this frame is staying, it is worth
   regenerating tall at some point; this is the most that can be done with
   the file that exists.

   Both declarations live where they always did -- the hero's at the top
   of this file, the foot's in THE LAST BAND GETS THE LAST LIGHT above.
   Nothing is overridden down here; this block is the note, not the rule.
   That is deliberate: three separate faults on this page have come from a
   stale declaration still matching a live selector, and a fourth pair
   would have been two more.
   ====================================================================== */
.sw-hero-simple::after{
  background:
    linear-gradient(180deg,
      rgba(15,13,12,.25) 0%, rgba(15,13,12,.15) 26%, rgba(15,13,12,.15) 42%,
      rgba(15,13,12,.21) 54%, rgba(15,13,12,.18) 68%, rgba(15,13,12,.12) 84%,
      rgba(15,13,12,.20) 100%),
    rgba(23,20,19,.31);
}
/* the two that have to carry the lighter ground */
.sw-hero-rail > button{color:#F6F1EA}
/* rgba(246,241,234,.68), the site's body token -- what home's .hx-sub,
   planning's .pl-sub and this page's own section copy all compute to.
   It was full cream, which made the hero's supporting line brighter than
   every other piece of supporting copy on the site and read as a second
   headline rather than as the sentence under one.

   It went to full cream when the hero had no wash and everything in it
   was struggling for contrast. The frame sits at .28 now and the ground
   behind this line is near rgb(37,28,24), so .68 measures comfortably --
   checked in the same pass. */
.swa-cap{color:rgba(246,241,234,.68)}
/* THE CAPTION'S LINES COME OUT EVEN.

   text-wrap:balance tells the browser to find the line breaks that make
   every line roughly the same length, instead of filling each one to the
   edge and leaving whatever is left on the last. That is what put a
   single word alone on the last line of the dashboard caption.

   It only does this for short blocks -- Chromium stops at six lines, so
   it is safe on a four-line caption and does nothing on a paragraph.
   Browsers without it fill greedily as before, which is the behaviour
   this replaces, so there is nothing to fall back to. */
.swa-cap,.swa-cap > span{text-wrap:balance}

/* THE NEW FRAME IS BRIGHTER, SO THE WASH COMES BACK UP A LITTLE.

   x0.50 was measured against the frame before this one. On this sky the
   same wash gave the eyebrow 4.55 and the caption 4.61 -- passing, but
   with five hundredths of headroom, and the crop moves with viewport
   height so the bright patch behind them is not fixed.

   x0.60 of the original wash. Still much lighter than the x0.74 it
   started at, and the blue is still the blue. */
.sw-hero-simple::after{
  background:
    linear-gradient(180deg,
      rgba(15,13,12,.30) 0%, rgba(15,13,12,.18) 26%, rgba(15,13,12,.18) 42%,
      rgba(15,13,12,.25) 54%, rgba(15,13,12,.22) 68%, rgba(15,13,12,.14) 84%,
      rgba(15,13,12,.24) 100%),
    rgba(23,20,19,.372);
}


/* ======================================================================
   THE HERO FRAME IS BLUE OVER RED

   Home's hero is cool blue-grey sky, a hot band at the horizon, dark
   red-brown ground. This is the same structure, composed for a layout
   where the application window covers the middle.

   Measured: the warm seam sits at 77% of the frame's height. The hero
   is 1440x1160 and the image is wider than that, so cover fills the
   height and the whole frame is visible top to bottom. That puts the
   seam at y 893 -- behind the window in the centre, but the window is
   1060 wide in a 1440 band, so the seam shows in the 190px either side
   of it. Blue behind the type, red under the window, and the orange
   running out to both edges.
   ====================================================================== */


/* ======================================================================
   THE HERO FRAME IS WEBP, AND THAT IS THE BANDING FIX

   The bands in the sky were not the grade. Counting hard steps down a
   sky column: the source has 16, the graded pixels in memory have 18,
   PNG keeps 18 -- and JPEG turned it into 29. Raising JPEG quality made
   it WORSE, 31 at q0.99, because the encoder spends its budget
   preserving the dither as blocky structure and coarsens the gradient
   underneath it.

   WebP at q0.86: 13. Smoother than the source, in 55KB against JPEG's
   177. Every browser this site supports reads it, and home already
   serves .webp.
   ====================================================================== */

/* ======================================================================
   NO WASH ON THE HERO

   Her call, made after seeing what it costs. The frame shows as
   generated -- the sky is the sky, with nothing sitting on top of it.

   What it costs, measured against the brightest ground behind each:

     headline  2.72   (needs 3)
     eyebrow   2.46   (needs 4.5)
     tabs      2.20   (needs 4.5)
     caption   1.89   (needs 4.5)

   Every piece of copy in the hero is under the readable threshold, the
   caption worst at 1.89, which is roughly light grey on light grey
   rather than a near miss.

   Recoverable without bringing a wash back -- a shadow behind the copy,
   a plate behind the caption strip, or moving the type down onto the
   darker half of the frame. Left here deliberately and noted so that
   whoever reads this next knows it is an open state rather than an
   oversight.
   ====================================================================== */
.sw-hero-simple::after{background:none}


/* ======================================================================
   THE SELECTED TAB IS CREAM

   Her pick from nine candidates measured against the shipped sky. The
   sheet those numbers came from:

     cream       #F6F1EA   2.48 on sky   16.31 on the dark sections
     peach       #E4BCAC   1.61          10.55
     clay        #B28479   1.16           5.65
     deep clay   #6E4238   3.01           2.18
     oxblood     #6B2419   3.98           1.65
     slate blue  #2F4459   3.60           1.83
     dark grey   #2A2523   5.42           1.21
     ground      #171413   6.56           1.00

   Nothing clears 4.5 in both places, because the sky behind the rail is
   rgb(150,155,164) -- a middle tone, which excludes light and dark by
   definition. Cream is the best of the light end and the brightest thing
   available, so the rail goes cream and the accent stays clay everywhere
   else on the page.

   HUE CAN NO LONGER SIGNAL THE SELECTION, because the other three tabs
   were already cream. So the cue moves into weight:

     unselected  cream at .62, hairline at .22
     selected    cream at full, underline at full and 3px

   A 0.38 opacity gap plus a hairline going from .22 to opaque and half
   again as thick is a stronger cue than the clay hue ever was -- clay
   measured 1.16 against this sky, which is to say the old highlight was
   not visible as a colour at all.
   ====================================================================== */
.sw-hero-rail > button{color:rgba(246,241,234,.62)}
.sw-hero-rail > button::after{background:rgba(246,241,234,.22)}
.sw-hero-rail > button:hover{color:#F6F1EA}
.sw-hero-rail > button:hover::after{background:rgba(246,241,234,.45)}
.sw-hero-rail > button[aria-selected="true"]{color:#F6F1EA}
.sw-hero-rail > button[aria-selected="true"]::after{background:#F6F1EA;height:3px}


/* ======================================================================
   BOTH PHOTOGRAPHS COME UP ON A PHONE

   The washes were mixed for a desktop band, where the picture runs the
   full 1440 and the type sits in the middle of it. At 390 the same
   percentage covers a frame a quarter as wide, showing a much smaller
   and much flatter slice of the image -- so it reads far heavier, and
   both bands came out as dark rectangles with a suggestion of desert in
   them.

   .60 -> .40 on the proof band and .78 -> .58 on the foot.

   AT THE END OF THE FILE ON PURPOSE. Both base rules are declared around
   line 1990, and a media query adds no specificity -- so the first
   version of this went into the phone block at line 900 and lost to
   them, and the computed wash came back .60 while the file read as
   though it had been changed. That is the third time this pattern has
   cost a round trip today, and the rule that avoids it is simple: an
   override goes AFTER the thing it overrides, not wherever its topic
   lives.
   ====================================================================== */
@media(max-width:760px){
  .swx-proof::after{background:rgba(15,13,12,.40)}
  .swx-price::after{background:rgba(15,13,12,.58)}
  /* The frame is 2.5:1 and the band at 390 is about 1:1.4, so cover
     scales it roughly 3.6x and shows a 390px slice of a 2880px picture.
     At the default 50% that slice is the middle, which on this frame is
     open ground -- the cactuses are out at the left and right thirds.
     18% lands on the pair at the left. */
  .swx-proof::before{background-position:18% 50%}

  /* ================== THE TREE STANDS UP ==================

     It was 850px wide in a 348px window and scrolled sideways. That is
     what a wide chart does on a phone, but it meant the shape of the org
     -- the whole point of the view -- could only ever be seen a third at
     a time.

     A flex tree is a tree because each ul is a ROW of children under one
     parent. Turn those rows into columns and the same markup becomes an
     indented list: every box full width, each level stepped in from the
     one above, connectors running down the left instead of across the
     top. No horizontal scroll, and the hierarchy still reads because the
     indent carries it.

     The li::before/::after elbows are the horizontal connectors, so they
     are replaced by one vertical rule down each ul plus a short stub
     into each box.

     AT THE END OF THE FILE, because .swa-tree's flex rules are declared
     at line 1294 -- the first version of this went in the phone block at
     line 860 and lost to them, and the tree measured 579px wide on three
     rows while the file read as though it were a column. */
  /* THE OUTLINE. One column, depth by indent, with a rail down each
     level where the connectors used to run.

     This reverses an earlier decision, on her call after seeing three
     options side by side at 440. The version rejected then was a bare
     indented list; what was wrong with it was not the indenting but
     that the seats had no weight -- a chart had been turned into a set
     of lines. Here every seat is a full-width box at its own depth, the
     rail draws the reporting line, and a short tick joins each box to
     its parent's rail. The shape is still "these hang off that"; it is
     read down the page instead of across it.

     What this buys over the wrapping two-up chart it replaces: at 440
     each seat gets the full column, so a role, a name and two
     responsibilities each fit on ONE line at readable sizes -- the
     two-up version had 142px to hold 179px of content and was setting
     names at 12px. And nothing can spill sideways, because nothing is
     centred and nothing is beside anything.

     AT THE END OF THE FILE, because .swa-tree's flex rules are declared
     at line 1343 and an earlier attempt at this lost to them. */
  .swa-tree{display:block;width:auto;margin:0}
  .swa-tree ul{
    display:block;position:static;
    /* 13 of margin then 19 of padding: the rail sits under the middle
       of the parent's avatar, and the tick reaches from it to the
       child's edge. */
    margin:0 0 0 13px;padding:0 0 0 19px;
    border-left:1px solid rgba(246,241,234,.14);
  }
  /* the desktop stem down into each group */
  .swa-tree ul::before{display:none}
  .swa-tree li{
    display:block;flex:none;min-width:0;max-width:none;
    padding:0;position:relative;
  }
  .swa-tree li:only-child{flex-basis:auto;max-width:none}
  .swa-tree ul ul li{flex:none;max-width:none}
  /* the desktop elbows */
  .swa-tree li::before,
  .swa-tree li::after{display:none}
  /* the tick from the rail into the box. Two type selectors, so it
     beats the display:none directly above it. */
  .swa-tree ul > li::before{
    content:"";display:block;position:absolute;
    left:-20px;top:23px;width:14px;height:1px;
    background:rgba(246,241,234,.14);
    border:0;transform:none;
  }
  .swa-tree ul > li::after{display:none}
  .swa-tree > li{padding-top:0}
  .swa-tree > li::before,
  .swa-tree > li::after{display:none}
  /* NO ZOOM CONTROL, AND NO GRID PAPER. "Recenter / - / +" are the
     handles of a canvas you pan, and there is no canvas here any more;
     leaving them would promise an interaction the layout no longer has.
     The dotted ground goes with them -- it reads as graph paper behind
     a diagram, and this is a list. */
  .swa-zoom{display:none}
  .swa-canvas{background-image:none;padding:14px 12px 16px}
  .swa-canvas-scroll{overflow:visible}
  /* THE DIRECTORY DROPS THE COLUMNS A PHONE CANNOT HOLD.

     Six of them -- name, contact, schedule, location, birthday, last
     login -- come to 617px in a 348px window. Nothing about that table
     is wrong; six columns is simply more than a phone has room for.

     Name and contact stay, which is what a directory is FOR: who they
     are and how to reach them. The rest are what you scroll a desktop
     table sideways to see, and the point of this window is to look like
     an app, not like a spreadsheet that got away.

     display:none rather than a scroll, because the earlier org-chart
     scroll was the thing she asked to be rid of. */
  .swa-dir th:nth-child(n+3),
  .swa-dir td:nth-child(n+3){display:none}
  .swa-dir th,.swa-dir td{padding-left:0;padding-right:10px}

  /* THE SEAT, AT FULL COLUMN WIDTH.

     It was 9px labels and 12px names, shrunk to survive a 142px box.
     With the column to itself it can be read at the sizes the rest of
     the site uses: a tracked 10px role, a 16px name, 13px of what the
     seat is for -- each on one line at 440. */
  .swa-seat{
    display:block;min-width:0;
    /* width:auto, because the desktop rule pins it to 140px -- five
       leaves plus gaps had to fit one row at 1440. There is no row here;
       the seat takes the column. Without this the boxes stayed 140 wide
       in a 348 tree and the outline read as a narrow ribbon down the
       left. */
    width:auto;
    padding:12px 14px;margin:0 0 8px;
    background:rgba(246,241,234,.028);
    border:1px solid rgba(246,241,234,.09);
    white-space:normal;
  }
  .swa-seat > b{
    display:block;margin:0 0 7px;
    font-size:10px;letter-spacing:.14em;
  }
  .swa-seat > span{display:flex;align-items:center;gap:9px}
  .swa-seat > span i{width:26px;height:26px;font-size:10px}
  .swa-seat > span u{font-size:16px}
  /* the desktop rule sets nowrap + ellipsis on this, for a box that had
     no room; here it has the width to say the whole thing */
  .swa-seat > em{
    display:block;margin:8px 0 0;font-size:13px;line-height:1.45;
    white-space:normal;overflow:visible;text-overflow:clip;
  }
  /* A SEAT THAT LEADS OTHERS is tinted, so the three levels are legible
     without counting indents. :has(> ul) is "this li contains a nested
     list", which is exactly what having reports means in this markup.
     The app's own accent, not the site's clay -- this is inside a
     drawing of software and should stay in its palette. */
  .swa-tree li:has(> ul) > .swa-seat{
    border-color:color-mix(in srgb, var(--swa-app-accent) 46%, transparent);
    background:color-mix(in srgb, var(--swa-app-accent) 9%, transparent);
  }
}

/* ---------------------------------------------------------------------
   BANDS ACROSS THE HERO BACKGROUND.

   .sw-hero-simple::before is desert-dusk.webp at opacity .28 under
   saturate(.6) brightness(.74). A sky is a long, almost flat gradient;
   at 28% opacity over a near-black ground it has only a handful of
   output levels left to describe itself in, so neighbouring values land
   on the same one and the ramp resolves into plates with visible edges.
   Exactly the same cause as the vertical banding on the planning
   video, and the same answer: dither.

   A tiled feTurbulence breaks the plates up so the eye reconstructs the
   ramp. It goes on ::after, which sits above the picture at z-index 1
   and carries no image of its own, and the alpha is baked into the SVG
   so ::after's own wash is left alone.

   FINER AND FAINTER THAN THE FIRST VERSION. Dither trades banding for
   grain, and at 6% over two octaves the grain was the more visible of
   the two -- she saw it straight away. One octave at baseFrequency 1.4
   makes the noise finer than the banding it is hiding, and 2.8% is the
   least that still carries the ramp. Below about 2% the plates return.
   --------------------------------------------------------------------- */
.sw-hero-simple::after{
  background-image:url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'>\
<filter id='n'><feTurbulence type='fractalNoise' baseFrequency='1.4' numOctaves='1' stitchTiles='stitch'/>\
</filter><rect width='160' height='160' filter='url(%23n)' opacity='.028'/></svg>");
  background-size:160px 160px;
  background-repeat:repeat;
}
