/* UpstreamIt — local app.
   Shares the token set with progress/index.html so the two pages read as one
   tool. One palette, light, on every screen: the app is read next to a job
   board and a resume, and those are white.

   The palette is drawn from the mark. `--ink` is the navy of the wordmark
   (#151926) and the greys are tinted toward it, so the whole page sits in the
   logo's hue rather than a neutral grey the mark has to fight. `--accent` is
   the logo blue taken down a step: the logo's own #647ED3 carries white button
   text at only 3.8:1, and #4c6acd reads as the same blue at 4.9:1. The mark
   itself keeps the true #647ED3 — see `.mark-ico` below. */

:root{
  --bg:#f7f8fa; --panel:#ffffff; --line:#e4e6ee; --line-soft:#eef0f6;
  --ink:#151926; --ink-2:#525a70; --ink-3:#868ea3;
  --accent:#4c6acd; --accent-soft:#eef1fc; --accent-ink:#ffffff;
  --ok:#0f7a4f; --ok-soft:#e8f6ef;
  --warn:#a05a00; --warn-soft:#fdf3e3;
  --err:#b42318; --err-soft:#fdecea;
  --radius:12px;
  --mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;
  --display:"IBM Plex Sans Condensed","IBM Plex Sans",-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif;
  --sans:-apple-system,BlinkMacSystemFont,"Segoe UI",Inter,system-ui,sans-serif;
}

*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--ink);font-family:var(--sans);
     font-size:14px;line-height:1.5;-webkit-font-smoothing:antialiased}
a{color:inherit}
button{font:inherit;color:inherit}

/* ------------------------------------------------------------------ header */
header{position:sticky;top:0;z-index:20;background:color-mix(in srgb,var(--bg) 88%,transparent);
       backdrop-filter:blur(12px);border-bottom:1px solid var(--line)}
.bar{max-width:1560px;margin:0 auto;padding:11px 20px;display:flex;align-items:center;gap:14px;flex-wrap:wrap}
/* The wordmark, one rule for every screen it appears on: the app header and
   the account pages. It is the only thing in the app set in the display cut,
   and it reads the same in both places because it is the same rule. */
.mark{font-family:var(--display);font-weight:700;font-size:18px;letter-spacing:-.01em;
      color:var(--ink);text-decoration:none;display:inline-flex;align-items:center;
      gap:5px;white-space:nowrap}
.mark .it{color:#647ED3}
a.mark:hover{color:var(--accent)}
/* The glyph is the favicon at reading size. It keeps its own brand blue rather
   than taking currentColor, because the wordmark next to it goes accent on hover
   and a mark that changes colour with a hover state stops being a mark. It is a
   letterform, not a square chip, so the box is 17x23 and `flex:0 0` keeps the
   header wrapping at narrow widths from squashing it out of proportion. */
.mark-ico{width:17px;height:23px;flex:0 0 17px;display:block}
.corpus{color:var(--ink-3);font-size:12px;font-variant-numeric:tabular-nums}
.spacer{flex:1}

select,input[type=text],input[type=number],input[type=search]{
  background:var(--panel);border:1px solid var(--line);border-radius:8px;
  padding:6px 9px;font:inherit;font-size:13px;color:var(--ink);min-width:0}
input:focus,select:focus,button:focus-visible{outline:2px solid var(--accent);outline-offset:1px}

.btn{background:var(--panel);border:1px solid var(--line);border-radius:8px;
     padding:6px 11px;font-size:13px;cursor:pointer;white-space:nowrap}
/* `Sign in` is an anchor — it goes to a screen with an address, so cmd-click
   and "open in new tab" should do what they say. It still has to sit in the
   header line looking like the buttons either side of it. */
a.btn{display:inline-flex;align-items:center;text-decoration:none;color:inherit}
.btn:hover{border-color:var(--ink-3)}
.btn.primary{background:var(--accent);border-color:var(--accent);color:var(--accent-ink);font-weight:550}
.btn.ghost{background:transparent;border-color:transparent;color:var(--ink-3)}
.btn.ghost:hover{color:var(--ink);border-color:var(--line)}
.btn[disabled]{opacity:.45;cursor:default}

/* ------------------------------------------------------------- filter sets */
/* The header control that says which saved search is on screen.

   It was a bare <select> reading "NYC · entry level · solutions & operations"
   with a button reading "Save" beside it, and neither said what it was: the
   menu could have been a sort order, and the button could have been saving a
   job. So the control carries its own label, the menu says whose each set is
   and where it lives, and a chip appears the moment the filters stop matching
   the set they came from — the one thing that makes "you can save this" a fact
   on screen rather than something you have to already know. */
.filterset{display:flex;align-items:center;gap:10px;position:relative}

/* One height for everything standing in the header line. Three controls at
   three heights — a two-line picker, a small pill, a button — read as three
   unrelated things dropped next to each other, which is what the row looked
   like before this. */
.bar .btn{height:34px;display:inline-flex;align-items:center}

.fs-pick{display:flex;flex-direction:column;align-items:flex-start;justify-content:center;
         gap:1px;text-align:left;height:34px;
         background:var(--panel);border:1px solid var(--line);border-radius:9px;
         padding:0 11px;cursor:pointer;max-width:340px}
.fs-pick:hover{border-color:var(--ink-3)}
.fs-pick[aria-expanded="true"]{border-color:var(--ink-3)}
.fs-cap{font-size:9.5px;text-transform:uppercase;letter-spacing:.08em;
        color:var(--ink-3);font-weight:600;line-height:1.3}
.fs-line{display:flex;align-items:center;gap:8px;max-width:100%}
.fs-name{font-size:13px;font-weight:550;line-height:1.3;
         white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fs-name.none{color:var(--ink-3);font-weight:400}
.fs-caret{color:var(--ink-3);font-size:10px;flex:none}

/* Quiet on purpose. This is a fact about the filters, not a warning about
   them: an amber pill in the middle of the row read as something being wrong,
   and it was louder than the button that answers it. A dot the colour of that
   button, and grey text. */
.fs-edited{display:inline-flex;align-items:center;gap:6px;font-size:12px;
           color:var(--ink-3);white-space:nowrap}
.fs-edited::before{content:"";width:5px;height:5px;border-radius:50%;background:var(--accent);flex:none}

/* The save button when there is something to save: tinted, not filled. A solid
   accent button is the loudest thing the page has, and it belongs to the form's
   own Save — the click that actually writes — not to the button that opens it. */
#save.ready{background:var(--accent-soft);color:var(--accent);font-weight:550;
            border-color:color-mix(in srgb,var(--accent) 32%,var(--line))}
#save.ready:hover{border-color:var(--accent)}

/* The menu.

   Styled as the app's own list of choices, not as a floating panel: the same
   hairline-separated rows, the same `--accent-soft` tint on the one that is
   selected, the same radius as the option lists in the left column. It used to
   be a rounded card with a deep drop shadow and a bright ✓ down the side, which
   is a different design language to everything it opens over — the page has no
   other floating card, and it marks a chosen row by tinting it. */
.fs-menu{position:absolute;top:calc(100% + 6px);left:0;z-index:40;overflow:auto;
         min-width:300px;max-width:min(420px,88vw);max-height:min(66vh,430px);
         background:var(--panel);border:1px solid var(--line);border-radius:9px;
         box-shadow:0 6px 18px rgb(0 0 0 / .07)}
.fs-group{padding:8px 10px 5px;font-size:10.5px;text-transform:uppercase;letter-spacing:.07em;
          color:var(--ink-3);font-weight:600}
.fs-group:not(:first-child){border-top:1px solid var(--line)}
.fs-item{display:block;width:100%;text-align:left;background:none;border:0;
         border-bottom:1px solid var(--line-soft);padding:6px 10px;cursor:pointer;font-size:13px}
.fs-item:last-child{border-bottom:0}
.fs-item:hover,.fs-item:focus-visible{background:var(--line-soft)}
.fs-item.on{background:var(--accent-soft)}
.fs-item .nm{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fs-item.on .nm{font-weight:600}
.fs-item .sub{display:block;font-size:11.5px;color:var(--ink-3);
              overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fs-empty{padding:9px 10px 11px;font-size:12px;color:var(--ink-3);line-height:1.45}
/* The row that acts on the rows above it, marked off the way the left column
   marks its "all boards" row: a full-strength rule and weight, never a tint —
   a tint here would read as "selected". */
.fs-foot{border-top:1px solid var(--line)}
.fs-foot .fs-item .nm{color:var(--ink-2);font-weight:600}

/* Naming a set. Small enough to sit under the button that opened it, so the
   filters it is about stay on screen while you name them. */
.fs-form{position:absolute;top:calc(100% + 6px);left:0;z-index:41;width:min(340px,88vw);
         display:flex;flex-direction:column;gap:7px;
         background:var(--panel);border:1px solid var(--line);border-radius:9px;padding:13px;
         box-shadow:0 6px 18px rgb(0 0 0 / .07)}
.fs-form h4{margin:0;font-size:13.5px;font-weight:600}
.fs-form p{margin:0;font-size:11.5px;color:var(--ink-3);line-height:1.45}
.fs-form p.err{color:var(--err)}
.fs-form .fs-field{font-size:11px;text-transform:uppercase;letter-spacing:.05em;
                   color:var(--ink-3);font-weight:600;margin-top:2px}
.fs-form input{width:100%}
.fs-form .row{display:flex;justify-content:flex-end;gap:7px;margin-top:3px}

/* ------------------------------------------------------------------ layout */
.layout{max-width:1560px;margin:0 auto;padding:18px 20px 100px;
        display:grid;grid-template-columns:320px minmax(0,1fr);gap:22px;align-items:start}
@media (max-width:1080px){.layout{grid-template-columns:1fr}}

aside{position:sticky;top:64px;max-height:calc(100vh - 84px);overflow:auto;
      display:flex;flex-direction:column;gap:10px;padding-right:4px}
@media (max-width:1080px){aside{position:static;max-height:none}}

/* ------------------------------------------------------------------- cards */
.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius)}
.card>h3{margin:0;padding:11px 13px;font-size:11px;text-transform:uppercase;
         letter-spacing:.07em;color:var(--ink-3);font-weight:600;
         display:flex;align-items:center;gap:8px;cursor:pointer;user-select:none}
.card>h3 .caret{margin-left:auto;color:var(--ink-3);transition:transform .15s;font-size:10px}
.card.collapsed>h3 .caret{transform:rotate(-90deg)}
.card.collapsed>.body{display:none}
.card>h3 .badge{background:var(--accent-soft);color:var(--accent);border-radius:99px;
                padding:1px 7px;font-size:10px;letter-spacing:0;text-transform:none;font-weight:600}
/* Sits beside the count and appears with it: nothing set, nothing to clear. */
.card>h3 .clear{background:none;border:0;border-radius:99px;padding:1px 6px;cursor:pointer;
                font:inherit;font-size:10px;letter-spacing:.04em;color:var(--ink-3);opacity:.7}
.card>h3 .clear:hover{color:var(--err);background:var(--err-soft);opacity:1}
.card>h3 .clear[hidden]{display:none}
.body{padding:0 13px 13px;display:flex;flex-direction:column;gap:9px}
.row{display:flex;gap:8px;align-items:center}
.row>*{min-width:0}
.hint{color:var(--ink-3);font-size:11.5px;line-height:1.45}

/* A captioned number box — `at most [ ] years`. Its own flex line, because as
   plain inline content the trailing unit wraps as soon as the caption, the box
   and the unit no longer fit in half a panel: `at most` kept its box on line one
   while `at least` centred a single line, so the pair of boxes in one .row sat
   at visibly different heights. Laying each out as a flex line pins them to one
   axis, and `min-width:0` on the box lets it shrink a few px instead of wrapping
   again when the panel is narrow. */
.field{flex:1 1 138px;display:flex;align-items:center;gap:5px;white-space:nowrap}
.field>input{flex:0 1 62px;min-width:34px}
.field.wide>input{flex:0 1 92px}
/* At the 320px sidebar a pair of these fits across with about a pixel to spare,
   which is how the wrap happened in the first place. Rather than trust that
   pixel, the pair is allowed to stack: below its basis the second field takes
   its own line at full width instead of squeezing both boxes to nothing. */
.row.pair{flex-wrap:wrap}

/* ------------------------------------------------------------------- chips */
.chips{display:flex;flex-wrap:wrap;gap:5px}
.chip{display:inline-flex;align-items:center;gap:5px;background:var(--accent-soft);
      color:var(--accent);border-radius:99px;padding:2px 4px 2px 9px;font-size:12px;font-weight:550}
.chip button{background:none;border:0;cursor:pointer;color:inherit;opacity:.6;
             font-size:14px;line-height:1;padding:0 4px;border-radius:99px}
.chip button:hover{opacity:1}
.chip.neg{background:var(--err-soft);color:var(--err)}
.chip.soft{background:var(--line-soft);color:var(--ink-2);font-weight:500;padding:2px 9px}

/* ------------------------------------------------------------- option list */
.options{display:flex;flex-direction:column;max-height:230px;overflow:auto;
         border:1px solid var(--line);border-radius:9px}
.opt{display:flex;align-items:center;gap:8px;padding:5px 9px;cursor:pointer;
     border-bottom:1px solid var(--line-soft);font-size:13px}
.opt:last-child{border-bottom:0}
.opt:hover{background:var(--line-soft)}
.opt input{margin:0;accent-color:var(--accent)}
.opt .lbl{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.opt .n{color:var(--ink-3);font-variant-numeric:tabular-nums;font-size:11.5px;font-family:var(--mono)}
.opt.zero .lbl,.opt.zero .n{opacity:.42}
.opt.on{background:var(--accent-soft)}
/* The one row that is not an option: it acts on the rows under it, so it is
   marked off from them by weight and a full-strength rule rather than by a
   background — a tint here would read as "selected", which is the one thing
   this row never is. */
.opt.all{font-weight:600;color:var(--ink-2);border-bottom:1px solid var(--line)}
.more{padding:6px 9px;color:var(--ink-3);font-size:11.5px}
/* Scoped, because the results column has its own `.more` further down that
   would otherwise centre this one and give it that row's padding. */
.options .more{display:block;padding:6px 9px;text-align:left;color:var(--ink-3);font-size:11.5px}
/* The same row, when there is something to click. It reads as the last option
   in the list rather than as a button floating under one, so the rule above it
   is the same hairline that separates two options. */
.options button.more{width:100%;background:transparent;border:0;border-top:1px solid var(--line-soft);
                     color:var(--accent);cursor:pointer;padding:7px 9px}
.options button.more:hover{background:var(--line-soft);color:var(--ink)}

/* The row you type your own cap into. Its input has to sit inside a 13px row
   without making that row taller than the presets above it, or the last option
   in the list reads as a different kind of thing than the four above it. */
.opt input[type=number]{width:60px;padding:1px 4px;font-size:13px;text-align:right;
                        margin:0 3px;border-radius:6px}
#age-custom .lbl{flex:1;overflow:visible}

/* A checkbox that is its own one-row list. Four controls on the page are a
   single boolean rather than a choice from a list, and each still owes the
   reader a count — so they get the option-row treatment, border and all, rather
   than being a bare checkbox floating between two bordered lists. */
.opt.standalone{border:1px solid var(--line);border-radius:9px}
.opt.standalone:last-child{border-bottom:1px solid var(--line)}

/* ------------------------------------------------- the unknown-answer panel */
/* Eleven criteria, each with the share of the corpus that never answers it and
   a choice about what that means. The share is the point of the whole panel:
   `drop` on salary is a defensible choice and `drop` on salary while not
   knowing it costs 62.8% of the market is not, so the number sits between the
   name and the buttons where it cannot be missed. */
.policy{display:grid;grid-template-columns:1fr auto;gap:2px 8px;align-items:center;
        padding:8px 0;border-bottom:1px solid var(--line-soft)}
.policy:last-child{border-bottom:0}
.policy .k{font-size:12.5px;color:var(--ink-2)}
.policy .share{grid-row:1;grid-column:2;font-family:var(--mono);font-size:11px;
               color:var(--ink-3);font-variant-numeric:tabular-nums;text-align:right}
.policy .seg{grid-column:1/-1;display:flex;border:1px solid var(--line);border-radius:7px;overflow:hidden}
.policy .seg button{flex:1;background:var(--panel);border:0;border-right:1px solid var(--line);
                    padding:3px 6px;font-size:11.5px;cursor:pointer;color:var(--ink-3)}
.policy .seg button:last-child{border-right:0}
.policy .seg button:hover{color:var(--ink);background:var(--line-soft)}
.policy .seg button.on{background:var(--accent);color:var(--accent-ink);font-weight:600}
/* `drop` is the only choice on this panel that can hide a job for a blank
   field, so the one that is armed says so in the colour it is armed in. */
.policy.changed .seg button.on{background:var(--warn);color:#fff}
.policy .note-line{grid-column:1/-1;color:var(--ink-3);font-size:11px;line-height:1.4}

/* ----------------------------------------------------------------- results */
.funnel{display:flex;flex-wrap:wrap;gap:0;background:var(--panel);border:1px solid var(--line);
        border-radius:var(--radius);overflow:hidden;margin-bottom:14px}
.step{padding:11px 15px;border-right:1px solid var(--line);flex:1;min-width:118px}
.step:last-child{border-right:0}
.step .v{font-size:19px;font-weight:600;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.step .l{color:var(--ink-3);font-size:10.5px;text-transform:uppercase;letter-spacing:.05em;margin-top:2px}
.step.hit .v{color:var(--accent)}

.notice{background:var(--warn-soft);color:var(--warn);border:1px solid color-mix(in srgb,var(--warn) 30%,transparent);
        border-radius:9px;padding:8px 12px;font-size:12.5px;margin-bottom:10px}
/* Amber is the engine talking about the match. Red is the page saying it could
   not reach the server, which is the one warning that also calls the numbers
   next to it into question. */
.notice.err{background:var(--err-soft);color:var(--err);
            border-color:color-mix(in srgb,var(--err) 30%,transparent)}

/* A search that never reached the server leaves the previous one's funnel,
   counts and rows sitting there, and they answer the profile as it was before
   the change that failed. Grey them until a search succeeds — an unreachable
   server must not be able to look like a successful search. `#warnings` is
   deliberately exempt: it is the only element in here still telling the truth.
   Dimmed, not disabled — a row you can already see is still a job you may want
   to open. */
#search-view.stale > *:not(#warnings){opacity:.34;filter:grayscale(1);transition:opacity .15s ease}

.sechead{display:flex;align-items:baseline;gap:10px;margin:22px 0 9px}
.sechead h2{font-size:12px;text-transform:uppercase;letter-spacing:.08em;color:var(--ink-3);
            font-weight:600;margin:0}
.sechead .sub{color:var(--ink-3);font-size:12px}
/* Sort and fold. They sit in the results heading rather than the filter rail
   because neither one is a filter: they change what the same match set looks
   like, not which jobs are in it. */
.sechead .spacer{flex:1}
.toolbar-opt{display:inline-flex;align-items:center;gap:5px;color:var(--ink-3);font-size:12px;
             white-space:nowrap;cursor:pointer}
.toolbar-opt input{margin:0;accent-color:var(--accent)}
.sechead select{padding:3px 7px;font-size:12px}

.jobs{display:flex;flex-direction:column;gap:7px}
.job{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
     padding:12px 14px;display:grid;grid-template-columns:30px minmax(0,1fr) auto;gap:12px;
     cursor:pointer;transition:border-color .12s}
.job:hover{border-color:var(--ink-3)}
.job.open{border-color:var(--accent)}
.rank{color:var(--ink-3);font-size:12px;font-variant-numeric:tabular-nums;font-family:var(--mono);padding-top:2px}

.job h4{margin:0 0 3px;font-size:14.5px;font-weight:600;letter-spacing:-.005em;line-height:1.35}
/* The link underline used to be the loudest thing on the card; thin it out so
   the title still reads as a link without swamping the company under it. */
.job h4 a{text-decoration-thickness:1px;text-underline-offset:2px;
          text-decoration-color:color-mix(in srgb,currentColor 32%,transparent)}
.job h4 a:hover,.job h4 a:focus-visible{text-decoration-color:currentColor}
/* The title is the only bold line on a card. The company is lifted out of the
   grey by ink, not by weight — a second semi-bold line sitting right under the
   heading competes with it instead of supporting it. The department stays a
   step further back so the eye still lands on the company first. */
.job .co{font-size:13px;line-height:1.4;font-weight:400}
.job .co b{color:var(--ink-2);font-weight:500}
.job .co .dept{color:var(--ink-3)}
.job .meta{display:flex;flex-wrap:wrap;gap:5px;margin-top:7px}
.job .why{color:var(--ink-3);font-size:11.5px;margin-top:6px;font-family:var(--mono)}
/* `.score` is the saved view's right-hand column now — status and a date. The
   search results used to print the raw ranking score here and no longer do. */
.score{text-align:right;font-variant-numeric:tabular-nums;color:var(--ink-3);font-size:12px;font-family:var(--mono)}
.score b{display:block;color:var(--ink);font-size:15px;font-weight:600}

/* ------------------------------------------------------- why it ranked */
/* What took the score's place in the third column. An icon rather than the word
   `why?`, because the word repeated down 200 rows became a column of text in
   its own right — louder than the thing it annotates, and the ordering is what
   the list is for. It is a faint dot at rest and only firms up on the row the
   pointer is over, so the column reads as texture until you go looking. */
.why-i{align-self:start;flex:none;width:19px;height:19px;padding:0;
       border:1px solid transparent;border-radius:50%;background:none;color:var(--ink-3);
       font-family:var(--sans);font-size:11.5px;font-style:italic;font-weight:700;
       line-height:17px;text-align:center;cursor:pointer;opacity:.3;
       transition:opacity .12s,color .12s,background .12s,border-color .12s}
.job:hover .why-i{opacity:1;border-color:var(--line)}
.why-i:hover{opacity:1;color:var(--accent);border-color:var(--accent)}
.why-i.on{opacity:1;background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
/* Nothing hovers on a touch screen, so there the icon is simply always legible. */
@media (hover:none){.why-i{opacity:.8;border-color:var(--line)}}
/* The same icon inline in the results line, where it is a picture of the
   control rather than the control — always lit, never clickable. */
.sub-hint{color:var(--ink-3)}
/* `middle` and not a pixel nudge: it centres the circle on the parent's own
   x-height, so the badge stays on the line if the results text ever changes
   size. A hard offset was tuned to one font-size and sat a few pixels low. */
.sub-hint .why-i{display:inline-block;vertical-align:middle;margin:0 1px;opacity:1;
                 border-color:var(--line);cursor:default}

.rank-why{grid-column:1/-1;border-top:1px solid var(--line-soft);margin-top:10px;padding-top:11px;cursor:auto}
.rank-why .head{font-size:12.5px;color:var(--ink-2);line-height:1.5;margin-bottom:6px}
.rank-why .head b{color:var(--ink);font-weight:600}
/* label | meter | number on one row, the sentence under it. The meter is the point:
   a component is only readable against the most it could have contributed. */
.rank-why .part{display:grid;grid-template-columns:minmax(88px,116px) minmax(56px,92px) auto;
                gap:3px 12px;align-items:center;padding:8px 0;border-top:1px solid var(--line-soft)}
.rank-why .k{font-size:10.5px;text-transform:uppercase;letter-spacing:.05em;color:var(--ink-3)}
/* Named `.meter`, not `.bar` — `.bar` is the page header. */
.rank-why .meter{height:6px;border-radius:99px;background:var(--line-soft);overflow:hidden}
.rank-why .meter i{display:block;height:100%;background:var(--accent);border-radius:99px}
.rank-why .n{font-family:var(--mono);font-size:11px;font-variant-numeric:tabular-nums;color:var(--ink-3)}
.rank-why .txt{grid-column:2/-1;font-size:12.5px;line-height:1.5;color:var(--ink-2)}
.rank-why .part.off{opacity:.5}
.rank-why .foot{color:var(--ink-3);font-size:11.5px;line-height:1.5;margin-top:11px;
                border-top:1px solid var(--line-soft);padding-top:9px}
@media (max-width:760px){
  .rank-why .part{grid-template-columns:minmax(88px,116px) minmax(0,1fr) auto}
  .rank-why .txt{grid-column:1/-1}
}

.detail{grid-column:1/-1;border-top:1px solid var(--line-soft);margin-top:10px;padding-top:11px;
        max-height:60vh;overflow:auto;cursor:auto}
.detail .desc{font-size:13.5px;line-height:1.62;color:var(--ink-2);white-space:pre-wrap;word-break:break-word}
.detail .desc h1,.detail .desc h2,.detail .desc h3{font-size:14px;color:var(--ink);margin:14px 0 5px}
.detail .desc ul{padding-left:20px}
.detail .desc p{margin:0 0 9px}
.detail .kv{display:grid;grid-template-columns:130px 1fr;gap:3px 12px;font-size:12.5px;margin-bottom:12px}
.detail .kv dt{color:var(--ink-3)}
.detail .kv dd{margin:0;font-family:var(--mono);font-size:12px;word-break:break-word}
.detail .actions{display:flex;gap:8px;margin-bottom:12px;flex-wrap:wrap}

.more{display:flex;align-items:center;justify-content:center;gap:10px;padding:16px 0 2px}
.more-note{color:var(--ink-3);font-size:12px}

.empty{background:var(--panel);border:1px dashed var(--line);border-radius:var(--radius);
       padding:34px 20px;text-align:center;color:var(--ink-3)}
.empty b{display:block;color:var(--ink);font-size:15px;margin-bottom:5px;font-weight:600}

.loading{position:fixed;top:0;left:0;right:0;height:2px;background:var(--accent);
         transform-origin:left;transform:scaleX(0);transition:transform .25s;z-index:50}
.loading.on{transform:scaleX(.75)}

footer{max-width:1560px;margin:0 auto;padding:0 20px 40px;color:var(--ink-3);font-size:11.5px}
kbd{font-family:var(--mono);background:var(--line-soft);border:1px solid var(--line);
    border-radius:5px;padding:1px 5px;font-size:11px}

/* --------------------------------------------------------------- accounts */
/* Optional, and the page says so: signed out there is one button in the header
   and every control above still works. Nothing here gates the search. */
/* Any author `display` rule outranks the UA stylesheet's [hidden] { display:none },
   so a flex element with the attribute set stays on screen. Without this the
   signed-out and signed-in header both render at once, and "Continue with
   Google" appears on a server where Google sign-in is not configured. */
[hidden]{display:none !important}
.acct{display:flex;align-items:center;gap:6px;position:relative}
.star{background:none;border:0;cursor:pointer;font-size:15px;line-height:1;padding:2px 0 0;
      color:var(--ink-3);transition:color .12s,transform .12s}
.star:hover{color:var(--warn);transform:scale(1.15)}
.star.on{color:var(--warn)}
.star[disabled]{opacity:.5;cursor:default}
#saved-toggle.on{background:var(--accent);border-color:var(--accent);color:var(--accent-ink);font-weight:600}

.menu{position:absolute;top:calc(100% + 7px);right:0;z-index:40;min-width:210px;
      background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:5px;
      box-shadow:0 10px 30px rgb(0 0 0 / .13)}
.menu .who{padding:7px 9px 8px;color:var(--ink-3);font-size:11.5px;border-bottom:1px solid var(--line-soft);
           margin-bottom:4px;word-break:break-all}
.menu .item{display:block;width:100%;text-align:left;background:none;border:0;border-radius:7px;
            padding:7px 9px;font-size:13px;cursor:pointer}
.menu .item:hover{background:var(--line-soft)}
.menu .item.quiet{color:var(--ink-3);font-size:12px}

/* ------------------------------------------------------- the saved tracker */
/* Status, note and lists, shown inside an opened job and on every saved row.
   Three separate questions — where it stands, what you told yourself about it,
   and which of your own lists it belongs to — so three separate controls. */
.tracker{border-top:1px solid var(--line-soft);margin-top:10px;padding-top:10px;
         display:flex;flex-direction:column;gap:7px;cursor:auto}
.saved-job .tracker{border-top:0;padding-top:8px;margin-top:8px}
.track-line{display:grid;grid-template-columns:52px minmax(0,1fr);gap:9px;align-items:center}
.track-label{color:var(--ink-3);font-size:11px;text-transform:uppercase;letter-spacing:.05em}
/* The segmented control. The page used to define `.seg` globally for the
   unknown-policy panel; that block went when the panel did, and the tracker is
   its only user now, so the rules live here scoped to it. Each stage carries
   its own colour — a tracker where "offer" and "rejected" look identical is one
   you have to read instead of glance at. */
.tracker .seg{display:flex;border:1px solid var(--line);border-radius:8px;overflow:hidden;max-width:430px}
.tracker .seg button{flex:1;background:var(--panel);border:0;border-right:1px solid var(--line);
                     padding:5px 4px;font-size:11.5px;cursor:pointer;color:var(--ink-3);white-space:nowrap}
.tracker .seg button:last-child{border-right:0}
.tracker .seg button:hover{color:var(--ink);background:var(--line-soft)}
.tracker .seg button.on{background:var(--accent);color:var(--accent-ink);font-weight:600}
.tracker .seg button.on[data-status="interviewing"]{background:var(--warn);color:#fff}
.tracker .seg button.on[data-status="offer"]{background:var(--ok);color:#fff}
.tracker .seg button.on[data-status="rejected"]{background:var(--err);color:#fff}
.note{width:100%;background:var(--panel);border:1px solid var(--line);border-radius:8px;
      padding:6px 9px;font:inherit;font-size:13px;color:var(--ink)}

.chip.toggle{border:1px solid var(--line);background:var(--panel);color:var(--ink-2);cursor:pointer;
             padding:2px 9px;font-weight:500}
.chip.toggle:hover{border-color:var(--ink-3)}
.chip.toggle.on{background:var(--accent-soft);border-color:transparent;color:var(--accent);font-weight:600}
.chip.toggle.new{color:var(--ink-3);border-style:dashed}
.chip.status{background:var(--accent-soft);color:var(--accent);font-weight:600;padding:2px 9px}
.chip.status[data-status="interviewing"]{background:var(--warn-soft);color:var(--warn)}
.chip.status[data-status="offer"]{background:var(--ok-soft);color:var(--ok)}
.chip.status[data-status="rejected"]{background:var(--err-soft);color:var(--err)}
.chip.warn{background:var(--warn-soft);color:var(--warn);font-weight:550;padding:2px 9px}

/* ---------------------------------------------------------- the saved view */
/* Your own list, full width: the filter sidebar belongs to the search, and a
   saved job stays here whether or not it still matches your current criteria. */
body.viewing-saved aside{display:none}
body.viewing-saved .layout{grid-template-columns:minmax(0,1fr)}
.scopes{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:12px}
.scope{display:inline-flex;align-items:center;gap:6px;background:var(--panel);border:1px solid var(--line);
       border-radius:99px;padding:4px 12px;font-size:12.5px;cursor:pointer}
.scope:hover{border-color:var(--ink-3)}
.scope.on{background:var(--accent);border-color:var(--accent);color:var(--accent-ink);font-weight:600}
.scope .n{font-variant-numeric:tabular-nums;font-family:var(--mono);font-size:11px;opacity:.75}
.scope .x{opacity:.45;font-size:14px;line-height:1;margin-left:1px}
.scope .x:hover{opacity:1}
.scope.new{border-style:dashed;color:var(--ink-3)}
.saved-job{cursor:auto}
.saved-job:hover{border-color:var(--line)}
.saved-job .score{text-align:right;white-space:nowrap}
.saved-job .score b{font-size:12.5px;font-weight:600;text-transform:lowercase}

/* ----------------------------------------------------- describe your search */
/* The one panel on the rail that is not a criterion. It sits above forty
   controls and its job is to fill them in, so it reads as the way in rather
   than as the first of forty: a tinted head, a real text area, and a result
   block that stays until the next thing you type. */
.card.ai{border-color:color-mix(in srgb,var(--accent) 26%,var(--line))}
.card.ai>h3{color:var(--accent);background:color-mix(in srgb,var(--accent-soft) 62%,transparent);
            border-radius:var(--radius) var(--radius) 0 0}
.card.ai.collapsed>h3{border-radius:var(--radius)}

#ai-text{width:100%;background:var(--panel);border:1px solid var(--line);border-radius:8px;
         padding:8px 9px;font:inherit;font-size:13px;color:var(--ink);resize:vertical;min-height:62px}
#ai-text:focus{outline:2px solid var(--accent);outline-offset:1px}
#ai-text:disabled{opacity:.55;cursor:not-allowed}

/* Recording is a state the page has to show plainly: a microphone that is on
   without saying so is the worst version of this control. */
#ai-mic.on{background:var(--err);border-color:var(--err);color:#fff;font-weight:550}
#ai-mic.on::before{content:"";display:inline-block;width:6px;height:6px;border-radius:50%;
                   background:#fff;margin-right:6px;animation:ai-pulse 1.1s ease-in-out infinite}
@keyframes ai-pulse{0%,100%{opacity:1}50%{opacity:.25}}

.hint.warn-note{color:var(--warn)}

.ai-result{display:flex;flex-direction:column;gap:7px}
.ai-line{margin:0;font-size:12.5px;line-height:1.5}
.ai-line.said{color:var(--ink-2)}
.ai-line.working{color:var(--ink-3);font-style:italic}
.ai-line.quiet{color:var(--ink-3)}
.ai-line.warn{color:var(--warn);background:var(--warn-soft);border-radius:7px;padding:6px 8px}
.ai-line.bad{color:var(--err);background:var(--err-soft);border-radius:7px;padding:6px 8px}

/* What it actually did, in the engine's own words rather than the model's — a
   summary is an account of itself, this is the list of criteria now in force. */
.ai-changes{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:3px}
.ai-changes li{font-size:12px;line-height:1.45;padding-left:16px;position:relative;color:var(--ink-2)}
.ai-changes li::before{position:absolute;left:0;font-family:var(--mono);font-weight:700}
.ai-changes li.add::before{content:"+";color:var(--ok)}
.ai-changes li.del::before{content:"\2212";color:var(--ink-3)}
.ai-changes li.del{color:var(--ink-3);text-decoration:line-through;text-decoration-color:var(--line)}

.ai-undo{align-self:flex-start;font-size:12px;padding:4px 8px;border-color:var(--line)}
