/* ══════════════════════════════════════════════════════════════════════════
   board-alert.css — the Review Board's alert panel. SST.
   turnerlee.com/shared/feedback/v1/
   ---------------------------------------------------------------------------
   Craig, 2026-08-24: "i really want the original SAVING with loading animation
   from the Review Board ... 'Success with Second Line' is the correct alert. I
   want these FOR ALL ALERTS. [The editor's] are made-up alerts that didn't exist
   before this. i want the established Alerts shown in the STATES page." And:
   "Uploading and Saving alerts are set and established here and should not be
   replaced by others."

   EXTRACTED VERBATIM from Content/Pages/reviews/settings.html lines 1315-1674,
   the page behind https://turnerlee.com/reviews/settings?project=18596&states=1 .
   Nothing retyped, nothing "cleaned up", every comment kept — they carry the
   decisions that produced these numbers and they are the reason the panel looks
   the way it does. The markup that fills it is that page's `toastFill()` at
   line 5448; the STATES list that exercises it is at line 10747.

   THE ONE ADDITION IS THE TOKEN BLOCK BELOW, and it is not tidiness. This sheet
   now runs on public pages built from the Blank template, which declares NO
   brand tokens at all — and a `var()` with nothing behind it does not keep the
   previous value, it falls back to INHERIT. Measured on the settings page
   2026-08-24 and written here as literals so the panel is the same panel
   wherever it opens. A page that HAS the tokens still wins: these are `var()`
   fallbacks, not overrides.

   Consumers: shared/editor/v1/text-edit.js (the in-context editor's alerts) and,
   when it is next touched, reviews/settings.html itself — one copy, so the two
   cannot drift. Edit HERE, bump ?v= in every consumer.
   ══════════════════════════════════════════════════════════════════════════ */

/* ---- A TOAST IS THE REFRESH PANEL -----------------------------------------
   Craig, 2026-08-16: "the Black 'Saving Settings...' toast at the bottom of the
   SETTINGS window on save, and any other toasts, should be GREEN and centered
   in the middle of the view window just like the REFRESHING window. I want that
   same CSS/style as the refresh on the Review Board site."

   THE VALUES ARE COPIED FROM `.mg-over` / `.mg-over-box` IN board.html, WHICH
   IS THE SOURCE OF TRUTH: the dimmed backdrop, the 18px radius, the green at
   rgba(31,150,74,.82), the white hairline, the 26/70 shadow and the .965 -> 1
   scale-in. They are restated here rather than shared because the Review Board
   is a client page and does not load this stylesheet - putting an admin sheet
   on it to save a duplicate would be the bigger mistake. If that panel is ever
   retuned, retune this with it.

   pointer-events:none SURVIVES THE REWRITE and is now load-bearing rather than
   incidental: this used to be a strip at the bottom of the screen and is now a
   full-viewport layer, so without it every toast would swallow three seconds of
   clicks on a page whose whole job is clicking.
   The z-index stays where it already was, on `#toast` further down, so there is
   still one statement of where a toast sits in the stack. */
/* ==============================================================
   BOOTSTRAP OWNS `.toast` TOO, AND IT WINS — MEASURED 2026-09-18 11:xx MDT.
   bootstrap.min.css ships `.toast:not(.show){display:none}`. `:not()` takes the
   specificity of its argument, so that is (0,2,0); this file's own `.toast` rule
   below is (0,1,0) and LOSES at any source order. This component adds `.on`, never
   `.show`, so on any page that loads Bootstrap the toast mounted, filled, got its
   class, and stayed `display:none` forever. Nothing errors. It reads as "the toast
   never fired".
   Measured on https://goepic4.com/ops/newsletters, live CSSOM: the only `.toast`
   rules in scope were bootstrap's three, and `.toast:not(.show)` was among them.
   THE REPEATED CLASS IS THIS FILE'S OWN IDIOM for winning a specificity contest
   without !important — see `.tlc-toast.tlc-toast` and `.is-warn.is-warn` in the
   sibling sheet. (0,3,0) beats Bootstrap's (0,2,0) wherever either sheet loads.
   ADDITIVE ON PURPOSE, not a rewrite of the selector below: MongooseSports
   /reviews/dashboard.html mounts a BARE `<div class="toast" id="toast">` with no
   `tlc-alert`, so narrowing the base rule to `.toast.tlc-alert` would have killed
   that page. This matches every consumer, old and new.
   ============================================================== */
.toast.toast.toast{display:grid}

.toast{position:fixed;inset:0;display:grid;place-items:center;padding:24px;
  opacity:0;pointer-events:none;transition:opacity .22s var(--ease);
  background:rgba(10,12,14,.42);backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px)}
.toast.on{opacity:1}
/* THE FILL WAS THIS TOOL'S OWN GREEN, NOT THE ESTATE'S. Craig, 2026-08-20:
   "Is the drop shadow changing the color that much? If so, I don't wanna drop
   shadow ... They are much brighter... I want the brighter established danger,
   warning and success colors with opacity like 0.9 opacity for these, want
   partial show thru. I also think there's a weird white border on these. I
   would love a border with 100% opacity in it's same color."

   NO, IT WAS NOT THE SHADOW - IT WAS THE COLOR. `0 26px 70px rgba(0,0,0,.42)`
   is cast outside the box and cannot tint a pixel of the fill, so the three
   things below are what made these read dull.

   THE SHADOW WENT ANYWAY, ONE MESSAGE LATER. Craig, 2026-08-20, once the color
   was right: "Can we remove the drop shadow entirely or make it really tight?
   It's making my eyes have weird edges." It is now `0 2px 10px rgba(0,0,0,.28)`
   and here is why he could suddenly see it: a 70px blur under a panel whose
   edge used to be a soft white 30%-alpha line reads as depth, and the same blur
   under a HARD, fully opaque, saturated border reads as fringing - two
   different edges half a pixel apart, which is exactly the "weird edges". The
   dark scrim plus the 3px backdrop blur were already doing the separating; the
   shadow was only ever the second half of a job that was finished.

   SYNCED UPSTREAM 2026-08-20, on Craig - shared/core/v1/feedback.css §18 now
   carries all three of these (fill .7, same-color stroke at full opacity,
   0 2px 10px) and the style guide documents them. The divergence note that used
   to stand here is discharged; this tool and the estate are one value again.
   THE DIRECTION MATTERS: this tool is where the component came from, so when
   these two disagree the question is which one is RIGHT, not which one is
   shared - and the answer goes upstream rather than being patched locally.

   The three that were dulling the fill:

   1. THE COLOR WAS WRONG AT THE SOURCE. This painted rgba(31,150,74,…) and
      rgba(192,57,43,…) - the tool's private green and --bad - while the estate's
      success and danger are #00b52b and #e60000, the same values .btn-green and
      .btn-danger wear four inches above this panel. feedback.css §18 says where
      it got them: "Hard-won geometry from SWC / MongooseSports Review Board -
      keep verbatim." This tool is where that component came FROM and had drifted
      off its own descendant.
   2. THE ALPHA, WHICH LANDED IN TWO STEPS. It was .82 on a color that was
      already dull, which is a real amount of black mixed in twice over - 18% of
      rgba(10,12,14,.42) plus the 3px blur. Craig called .9 first, then .7 once
      the bright values were in: "opacity should be changed to 0.7 for all of
      these states popup overlays." The order matters and is the reason .7 works
      now and would not have before - at #c0392b it would have read as mud; at
      #e60000 with a 100%-opacity border of the same color holding the edge, the
      fill can give up 30% and the panel still reads as red, because the BORDER
      is now what states the color and the fill only has to carry the text.
   3. THE WHITE RIM. `1px solid rgba(255,255,255,.30)` put a lighter,
      DIFFERENT-HUE line around every panel, which is what reads as "weird white
      border" and is also the thing that made the fill look grayer by contrast.
      The border is now the same color at FULL opacity - so the edge is the one
      place the true color is shown undiluted, and the fill sits just inside it.

   The tokens are declared in mg-admin.css next to the button colors, once, for
   both. */
/* 40px 50px ON EVERY TOAST, NOT JUST THE HELD ONE. Craig, 2026-08-20:
   "update padding on all, not just this one". The held error had picked up
   46px sides on its own so a long line would not run under the x, which left
   SAVING SETTINGS sitting in the old 18/22 four pixels away from a panel with
   more than twice the air. One number, every state - and 50px clears the x on
   its own, so the is-hold override that used to do that job is gone. */
.toast-box{width:min(350px,100%);padding:40px 50px;border-radius:18px;text-align:center;
  background:rgba(var(--fb-success-rgb),.7);border:1px solid var(--fb-success);
  box-shadow:0 2px 10px rgba(0,0,0,.28);color:#fff;
  font-family:var(--f-text);font-weight:300;font-size:20px;line-height:1.4;
  transform:scale(.965);transition:transform .22s var(--ease)}
/* GREEN IS A CLAIM, AND IT WAS BEING MADE ABOUT FAILURES. Craig, 2026-08-20:
   "I uploaded 2 files to v3. and i got a really long 'failed' message in a
   square green box overlay ... the overlay should have been 'danger' color
   alert." The fill was written once, for "N files in", and then every other
   message in the tool inherited it - including `name — why` from a rejected
   upload. A person reads the color before the words. */
.toast-box.is-bad{background:rgba(var(--fb-danger-rgb),.7);border-color:var(--fb-danger)}
/* 350px IS A WIDTH FOR "2 FILES IN". Craig, same message: "the overlay should
   have been much wider instead of wrapping a bunch of text out of bounds
   outside of the little green square bg." Two separate faults in that
   sentence:
     - too narrow. A gateway error carries a filename AND a reason and had
       350px to do it in, so it stacked into a tall thin column.
     - out of bounds. The error strings contain filenames and URLs, which have
       no space to break at, so a single long token ran straight through the
       padding and out of the box. `overflow-wrap:anywhere` is the half that
       actually stops the overflow; widening alone would only have moved it.
   is-wide rides the same >48 test as is-long, so a message long enough to be
   prose is also a message given room to be prose. */
.toast-box.is-wide{width:min(760px,100%)}
/* AN ERROR NEEDS TO SAY IT IS ONE BEFORE IT SAYS WHAT HAPPENED. Craig,
   2026-08-20: "messages like this need some sort of header, even if 'ERROR' or
   'UNKNOWN ERROR' appears in the header font."

   The panel had no headline on an error at all - `.toast-t.is-long` drops the
   caps treatment for anything past 48 characters, which every real failure is,
   so the message arrived as a bare sentence with nothing naming it. Red says
   "something is wrong" and the sentence says what; nothing said WHICH KIND of
   thing you are looking at, and that is the word a person repeats when they
   report it.

   So an error is now two elements: `.toast-t` keeps its job as the headline
   and always reads ERROR, and the reason moves to `.toast-m`, which is the
   prose treatment `.toast-t.is-long` already was. Success toasts are untouched
   - their message IS the headline. */
/* --f-ui, NOT --f-text, AND 400 RATHER THAN 300. Craig, 2026-08-20: "that
   secondary [font] is really hard to read on these alerts and stuff, is it
   possible to use Roboto (or whatever our standard sans serif font is) for
   that secondary."

   --f-text is Hypatia: a light humanist face for reading at length on a white
   page. Every alert surface below used it at weight 300, 14-19px, on saturated
   red or green, at the moment someone is trying to copy a filename out of an
   error - four conditions, all of them the opposite of what that face is for.
   The headline keeps --f-display; the brand still speaks. The part you have to
   READ is the reader's own system face, which is what --f-ui resolves to. See
   the token in mg-admin.css for why it is not a webfont and what putting it in
   'ID Brand Settings' would actually cost. */
/* THE TOAST'S OWN INK MUST OUTRANK A PAGE CONTEXT RULE, SO IT IS SCOPED UNDER .toast.
   Craig, 2026-09-10: "these alerts must have White text 100% of the time all the time across
   all sites ... There is no scenario where these should have Black text. this never should
   change."
   MEASURED on cololamb.com/ops/style-guide?brand=Operations#alerts: the ERROR toast rendered
   rgba(0,0,0,.85) on rgba(230,0,0,.7). The winner was
     `.onLt, .onLt div, .onLt span, .onLt p { color: var(--onLt_color3) }`   (0,1,1)
   at t_tlc-styles.css:839 -- the per-site legacy sheet -- matching `.onLt div`, because the
   style guide wraps each page in `div#page-alerts.page.onLt`. `.toast-t` and `.toast-m` were
   (0,1,0) and lost on SPECIFICITY, so source order could never have saved them.
   `.toast-box{color:#fff}` did not help either: it only INHERITS, and both children are matched
   DIRECTLY by `.onLt div`, so the inherited value never reaches them.
   `.toast .toast-t` is (0,2,0) and beats (0,1,1) on any site, with no !important -- the rule it
   has to beat has none. Do not "fix" this by adding !important; the next context rule would
   need one too and the component would stop being readable.
   TurnerLee does not show the bug only because it loads shared/core/v1/sst-styles.css and NOT
   t_tlc-styles.css. That is a per-site sheet difference, not a component difference. */
.toast .toast-m{margin:12px 0 0;color:rgba(255,255,255,.94);
  font-family:var(--f-ui);font-weight:400;font-size:18px;
  letter-spacing:0;text-transform:none;line-height:1.45}
/* the headline and the box ink ride the same scope, same reason */
.toast .toast-t,.toast .toast-s{color:#fff}
.toast .toast-box{color:#fff}
.toast-t,.toast-s,.toast-m{overflow-wrap:anywhere}
/* AN ERROR YOU CANNOT FINISH READING IS NOT A MESSAGE. Craig, 2026-08-20:
   "i want to review the alert that disappears fast" - and before that, of the
   failed upload, "i couldn't screenshot it quick enough."

   3.2s is a fine life for "2 files in". It is the wrong life for a gateway
   error carrying a filename and a reason, which is the one message on this
   page a person has to read twice and probably copy. So the timer is now a
   property of the NEWS, not of the panel: good news expires, bad news waits to
   be dismissed.

   pointer-events comes back ONLY while holding. The note on .toast above is
   right that `none` is load-bearing - this is a full-viewport layer and a
   passing toast must not eat three seconds of clicks on a page whose whole job
   is clicking. A held error is the exact inversion of that: it is not passing,
   and stopping the click that would have scrolled it away is the point. */
.toast.is-hold{pointer-events:auto;cursor:pointer}
/* THE BOX ITSELF IS NOT A DISMISS TARGET. Craig, 2026-08-20: "it should
   display until you click close or outside the bounds to close it, because
   how else does userDesigner know that it's an error? and i need my team to be
   able to notify me and give me a screenshot if there is an error."
   Screenshot AND notify - so the text has to survive being pointed at long
   enough to select and copy. Click-anywhere would have closed it under the
   first drag of a selection. Outside the box, Esc, or the x. */
/* SYMMETRIC padding, not just room on the right. The x is absolutely placed
   in the corner, so without this a long first line runs underneath it - and
   padding only one side would drag the centered text off center, which on a
   350px chip is the thing you notice before the message. */
.toast.is-hold .toast-box{cursor:default;user-select:text;-webkit-user-select:text;
  position:relative}
/* ---- tlc-shortcut, ported from sst-styles.css ---------------------------
   Craig, 2026-08-20: "X in top right corner must be my X in style guide
   shortcut buttons." It was a hand-drawn white disc with a times glyph in it -
   a fourth close control in an estate that has exactly one, and §17 is
   unusually blunt about why that is not allowed: "A mark that is missing from
   this set needs new artwork, not new CSS."

   Copied verbatim. The art URLs are already absolute to turnerlee.com in the
   source, so nothing has to be added to MongooseSports/img - the SST points
   every site at the one set on purpose. The rules are here for the same reason
   the buttons and the alerts are: sst-styles.css does not load on a
   Don't-Use-Template page. The class names are the estate's.

   HOW IT WORKS, because it is not obvious and it constrains what can be
   recolored: ::before is the OUTLINED file used as a MASK, painted in the ink,
   over a tint disc - which is what lets one pair of files be any color. Hover
   swaps the whole button's background to the PRE-COLORED filled twin and kills
   the mask. So ink and hover-fill are a matched pair measured out of the same
   artwork, which is exactly why §17 forbids swapping the ink for a brand
   token. */
/* NO `--tlc-shortcut-art:none` HERE, AND THAT IS THE WHOLE POINT. This file is a
   standalone copy of the shortcut base so the alert engine ships without the site
   sheet — but sst-styles.css owns the ART for every mark (plus, save, restore,
   nextday, dots, check) and those rules are `.tlc-shortcut-plus`, the same
   specificity as this `.tlc-shortcut`. Declaring the property here at all meant
   whichever sheet loaded LAST won, and on the style guide that is this one: every
   mark except `times`, which this file also defines, came out a bare grey disc.
   Craig, 2026-08-25: "What happened all the shortcut icons". The fallback moved
   into the var() references below, which behaves identically when this file loads
   alone and stops it clobbering the estate's art when it does not. */
.tlc-shortcut{--tlc-shortcut-size:31px;--tlc-shortcut-ink:#414042;
  --tlc-shortcut-tint:transparent;
  position:relative;flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;
  width:var(--tlc-shortcut-size);height:var(--tlc-shortcut-size);padding:0;
  border:0;               /* the ring is IN the art - a CSS border doubles it */
  border-radius:50%;background:var(--tlc-shortcut-tint);overflow:hidden;
  font-size:0;line-height:0;color:transparent;cursor:pointer}
.tlc-shortcut::before{content:'';position:absolute;inset:0;transform:none;
  background:var(--tlc-shortcut-ink);
  -webkit-mask:var(--tlc-shortcut-art, none) center / 100% 100% no-repeat;
          mask:var(--tlc-shortcut-art, none) center / 100% 100% no-repeat}
.tlc-shortcut::after{content:none;display:none}
.tlc-shortcut:hover{background:var(--tlc-shortcut-art-hover, none) center / 100% 100% no-repeat}
.tlc-shortcut:hover::before{content:none;display:none}
.tlc-shortcut:focus-visible{outline:2px solid var(--tlc-shortcut-ink);outline-offset:2px}
.tlc-shortcut:disabled,.tlc-shortcut.is-disabled{opacity:.4;pointer-events:none}
.tlc-shortcut-sm{--tlc-shortcut-size:20px}
.tlc-shortcut-times{--tlc-shortcut-ink:#FF0029;--tlc-shortcut-tint:#FBE0E4;
  --tlc-shortcut-art:url('https://turnerlee.com/img/schedule/times-circle-regular.svg');
  --tlc-shortcut-art-hover:url('https://turnerlee.com/img/schedule/times-circle-fill-red.svg')}

/* The toast's close IS one. This rule places and sizes it and sets no color,
   because the component owns that. */
.toast-close{position:absolute;top:12px;right:14px;--tlc-shortcut-size:26px}
/* MATCHED TO THE PANEL IT SITS ON. Craig, 2026-08-20: "change colors
   appropriate to success, danger, warning to match alert color bg." On the
   danger panel the default times pair IS the match, so nothing is overridden
   there. On a green panel the red pair reads as a foreign chip, so ink and
   tint become the estate's own green - the exact pair .tlc-shortcut-plus and
   -save already use, not a green invented here.

   HOVER CANNOT SWAP THE FILE, AND THAT IS AN ARTWORK FACT. There is no
   times-circle-fill-GREEN; §17: "A mark that is missing from this set needs
   new artwork, not new CSS." So on green the hover deepens the tint and KEEPS
   the mask rather than flipping to the red filled twin, which is the one
   outcome worse than leaving it red. If Craig draws the green times, delete
   these three lines and set --tlc-shortcut-art-hover instead. */
.toast-box:not(.is-bad) .toast-close{--tlc-shortcut-ink:#00C137;
  --tlc-shortcut-tint:#DFF7E4;--tlc-shortcut-art-hover:none}
.toast-box:not(.is-bad) .toast-close:hover{background:#bfeecd}
.toast-box:not(.is-bad) .toast-close:hover::before{content:'';display:block}

/* ---- THE STATES HARNESS -------------------------------------------------
   Craig, 2026-08-20: "we are creating this webpage this review board. I need
   to be able to test and review all of the alerts and things that disappear
   really quick otherwise we can't get those looking correct."

   ?states=1 only. It is NOT a second page showing lookalike markup - this
   estate has paid for that mistake more than once (mg-admin.css exists because
   two copies of one button drifted). Every entry calls the REAL function the
   real code path calls, so a state cannot be reviewed here and be different in
   production: if toastBad() changes, this changes with it or it stops running.
   PIN holds whatever fires next, including the successes, so a 3.2s panel can
   be looked at for as long as it takes. */
.mgst{position:fixed;left:18px;bottom:18px;z-index:9000;width:310px;max-height:78vh;
  overflow:auto;overscroll-behavior:contain;background:var(--panel);
  border:1px solid var(--line);border-radius:12px;
  box-shadow:0 18px 50px rgba(10,11,14,.28);font-family:var(--f-text);font-size:13px}
.mgst-h{position:sticky;top:0;background:var(--brand-3xd);color:#fff;padding:10px 12px;
  font-family:var(--f-display);font-weight:900;font-size:12px;letter-spacing:.16em;
  text-transform:uppercase;display:flex;align-items:center;gap:8px}
.mgst-h .mgst-pin{margin-left:auto;font-size:11px;letter-spacing:.1em;padding:4px 9px;
  border-radius:20px;border:1px solid var(--line-on-dark);background:none;color:#fff;
  cursor:pointer;font-family:var(--f-display)}
.mgst-h .mgst-pin[aria-pressed="true"]{background:var(--accent);border-color:var(--accent);
  color:var(--ink-on-bright)}
.mgst-g{padding:9px 12px 4px;font-family:var(--f-display);font-weight:700;font-size:10px;
  letter-spacing:.16em;text-transform:uppercase;color:var(--ink-3)}
.mgst button.mgst-i{display:block;width:calc(100% - 16px);margin:0 8px 5px;text-align:left;
  padding:7px 10px;border-radius:7px;border:1px solid var(--line-2);background:var(--panel-2);
  color:var(--ink-2);font:inherit;cursor:pointer}
.mgst button.mgst-i:hover{border-color:var(--accent);color:var(--accent-ink)}
.mgst-f{padding:8px 12px 11px;color:var(--ink-3);font-size:11px;line-height:1.45}
.mgst-f b{color:var(--ink-2);font-weight:700}
/* The way in. Quiet on purpose - it is a tool for the two people who build
   this page, not a feature of it - but present, because a doc nobody opens is
   not documentation. Centered under the shell so it reads as the end of the
   page rather than something floating on it. */
.mgst-link{max-width:var(--shell-max);margin:0 auto;
  padding:6px var(--shell-pad) 34px;text-align:right}
.mgst-link a{font-family:var(--f-ui);font-size:12px;letter-spacing:.04em;
  color:var(--ink-4);text-decoration:none;border-bottom:1px solid transparent}
.mgst-link a:hover{color:var(--ink-3);border-bottom-color:var(--ink-3)}
/* ---- the spinner, from board.html's .mg-over refresh panel --------------
   Craig, 2026-08-20: "these with timing and auto close, should use the loading
   animation above it like the refresh we use."

   It answers the only question a timed panel leaves open. SAVING SETTINGS…
   with nothing moving is indistinguishable from SAVING SETTINGS… that died
   three seconds ago, and this toast holds for 3.2s on a queue that measures
   12-22s per write - so the ellipsis was carrying the whole burden of "still
   going". A turning arc says it without a word.

   ONLY ON THE TIMED ONES, which is Craig's own boundary and the right one: a
   held error is finished - it is not waiting for anything, and a spinner over
   a failure would be a lie about what happens next.

   Values copied from board.html rather than re-tuned, including the 3.4rem
   note: "a 64px spinner over a 26px headline makes the loading indicator the
   biggest thing in a panel whose job is to say four words." Keyframes are
   prefixed mgo- there and mgt- here so the two pages cannot collide if a
   future refactor ever puts them in one document. */
.toast-spin{display:inline-block;width:3.4rem;height:3.4rem;margin:0 0 16px;
  font-size:0;animation:mgt-rotate 1568ms linear infinite}
.toast-spin .spinner-layer{position:absolute;width:100%;height:100%;opacity:1;border-color:#fff;
  animation:mgt-fill 5332ms cubic-bezier(.4,0,.2,1) infinite both}
.toast-spin{position:relative}
.toast-spin .gap-patch{position:absolute;top:0;left:45%;width:10%;height:100%;
  overflow:hidden;border-color:inherit}
.toast-spin .gap-patch .circle{left:-450%;width:1000%}
.toast-spin .circle-clipper{position:relative;display:inline-block;width:50%;height:100%;
  overflow:hidden;border-color:inherit}
.toast-spin .circle-clipper .circle{position:absolute;top:0;right:0;bottom:0;width:200%;height:100%;
  border-color:inherit;border-style:solid;border-width:.225rem;
  border-bottom-color:transparent;border-radius:50%}
.toast-spin .circle-clipper.left .circle{left:0;border-right-color:transparent;
  transform:rotate(129deg);animation:mgt-left 1333ms cubic-bezier(.4,0,.2,1) infinite both}
.toast-spin .circle-clipper.right .circle{left:-100%;border-left-color:transparent;
  transform:rotate(-129deg);animation:mgt-right 1333ms cubic-bezier(.4,0,.2,1) infinite both}
@keyframes mgt-rotate{to{transform:rotate(360deg)}}
@keyframes mgt-fill{12.5%{transform:rotate(135deg)}25%{transform:rotate(270deg)}
  37.5%{transform:rotate(405deg)}50%{transform:rotate(540deg)}62.5%{transform:rotate(675deg)}
  75%{transform:rotate(810deg)}87.5%{transform:rotate(945deg)}to{transform:rotate(1080deg)}}
@keyframes mgt-left{from{transform:rotate(130deg)}50%{transform:rotate(-5deg)}to{transform:rotate(130deg)}}
@keyframes mgt-right{from{transform:rotate(-130deg)}50%{transform:rotate(5deg)}to{transform:rotate(-130deg)}}
/* A spinner is a progress indicator, not decoration - frozen at .01ms it reads
   as a broken page, which is the opposite of reassuring. It keeps turning, as
   one plain slow rotation instead of the four-part arc. Same call board.html
   made. */
@media (prefers-reduced-motion:reduce){
  .toast-spin{animation-duration:2s!important}
  .toast-spin .spinner-layer,
  .toast-spin .circle-clipper .circle{animation:none!important}
}

/* THE SAME TWO LINES THE REVIEW BOARD'S REFRESH PANEL USES. Craig,
   2026-08-16: "SAVING SETTINGS needs to be all caps like ARTWORK HAS CHANGED
   on the refresh. add caption like Refresh saying: 'Review Board will update
   automatically upon save.'" A status panel that says what happened and what
   it means should say it the same way in both places. */
/* THE SAME DECLARATIONS AS .mg-over h2 / .mg-over p ON THE REVIEW BOARD, not
   an approximation of them. Craig, 2026-08-16: "Settings' SAVING modal/toast
   is not using this font css/styles from the Review Board."
   What was actually wrong: weight 700 against 900, .06em against .04em, and -
   the visible one - a 20px headline over a 17px line. The Review Board sets
   BOTH at --mgo-size and says why: "the headline and the line under it are the
   same 20px. The separation is weight and case, not size." Copying that rule
   meant copying its tokens too, so --mgo-size/--mgo-bump are declared here
   with the same values rather than the numbers being inlined. */
.toast{--mgo-size:clamp(20px,min(3.6vw,2.5vh),22px);--mgo-bump:0px}
.toast-t{margin:0;color:#fff;font-family:var(--f-display);font-weight:900;
  font-size:calc(var(--mgo-size) + var(--mgo-bump));line-height:1.15;
  letter-spacing:.04em;text-transform:uppercase}
/* SHORT IS A HEADLINE; LONG IS A SENTENCE. The failure messages run to a full
   line and are the ones a person actually has to READ - "COULD NOT SAVE AFTER
   4 TRIES. YOUR EDITS ARE STILL ON SCREEN..." is worse than useless. So the
   caps treatment is for the status lines it was asked for and steps aside for
   anything long enough to be prose. */
.toast-t.is-long{font-family:var(--f-ui);font-weight:400;font-size:18px;
  letter-spacing:0;text-transform:none;line-height:1.45}
.toast-s{margin:14px 0 0;color:rgba(255,255,255,.92);
  font-family:var(--f-ui);font-weight:400;
  font-size:calc(var(--mgo-size) - 2px);line-height:1.25}
.toast.on .toast-box{transform:scale(1)}
/* Same 14px the Review Board's panel drops to; a phone has no 24px to spend. */
/* 100px of side padding inside a 350px box is 30% of a phone screen spent on
   air. The box steps down with the layer it already stepped down with; the
   proportion Craig picked is what carries, not the literal on a 360px screen. */
@media (max-width:560px){ .toast{padding:14px} .toast-box{padding:26px 24px} }


/* ══════════════════════════════════════════════════════════════════════════
   THE FALLBACK LAYER — appended AFTER the extracted block, never inside it.

   Everything above reads `--ease`, `--fb-success[-rgb]`, `--fb-danger[-rgb]`,
   `--f-display`, `--f-ui` and `--f-text`, which are declared in mg-admin.css and
   exist on /ops and /reviews. This sheet now also runs on public pages built
   from the Blank template, where NONE of them are declared — and a var() with
   nothing behind it does not keep the previous value, it makes the declaration
   invalid, so the panel came up with no fill and a white rim. Measured
   2026-08-24: `background-color: rgba(0, 0, 0, 0)`.

   THE FIRST ATTEMPT AT THIS WAS `--fb-success-rgb: var(--fb-success-rgb, …)` ON
   `.toast`, AND IT IS WORTH THE WARNING: a custom property whose own value
   references itself is a CYCLE, which makes it guaranteed-invalid — so the token
   was not merely un-defaulted, it was destroyed, on the pages that had it too.

   Restating the four declarations with literal fallbacks is what works. Same
   selectors, same specificity, later in the file, so these win — and on a page
   that HAS the tokens each var() still resolves to the page's own value. Values
   measured off https://turnerlee.com/reviews/settings?project=18596 .
   ══════════════════════════════════════════════════════════════════════════ */
.toast { transition: opacity .22s var(--ease, cubic-bezier(.16,1,.3,1)); }
.toast-box {
  background: rgba(var(--fb-success-rgb, 0,181,43), .7);
  border: 1px solid var(--fb-success, #00b52b);
  font-family: var(--f-text, 'Hypatia','Helvetica Neue',Helvetica,Arial,sans-serif);
}
.toast-box.is-bad {
  background: rgba(var(--fb-danger-rgb, 230,0,0), .7);
  border-color: var(--fb-danger, #e60000);
}
.toast-t { font-family: var(--f-display, 'Nexa','Helvetica Neue',Helvetica,Arial,sans-serif); }
.toast-t.is-long,
.toast-s,
.toast-m { font-family: var(--f-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif); }

/* The layer. The settings page keeps its z-index on its own `#toast` further
   down that sheet; this component has no such element, and it has to clear the
   editor's own chrome. */
.toast { z-index: 2147483001; }

/* ══════════════════════════════════════════════════════════════════════════
   BOOTSTRAP OWNS `.toast` AS WELL, AND ON A PUBLIC PAGE IT WINS.

   Measured 2026-08-24 on turnerlee.com: the panel computed `display: none` and a
   0x0 rect with every one of its own rules loaded and correct. Bootstrap 5 ships
   `.toast:not(.showing):not(.show) { display: none }` — (0,3,0), so it outranks
   the plain `.toast` above at any source order — plus `width: 350px`, a rounded
   white card and a shadow, none of which this layer declares and all of which it
   would therefore inherit from Bootstrap.

   The settings page never met this because it does not load Bootstrap. Anything
   that puts this component on a public page does.

   So the layer carries a second class, `tlc-alert`, and the properties Bootstrap
   takes are restated against it. `!important` on the display, because specificity
   alone cannot beat a `:not()` chain — and scoped to that class, so a REAL
   Bootstrap toast elsewhere on the page is untouched.
   ══════════════════════════════════════════════════════════════════════════ */
.toast.tlc-alert {
  display: grid !important;
  width: auto;
  max-width: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  background-clip: border-box;
  font-size: inherit;
}
/* HIDDEN MEANS GONE — the `!important` above also beats `[hidden]`, including
   Bootstrap's `[hidden]{display:none!important}` at (0,1,0). So text-edit.js's
   `veil.hidden = true` after a save left a transparent, full-viewport layer at
   z-index 2147483001 — and Bootstrap 5.3's `.toast{pointer-events:auto}`, loaded
   after this sheet on sweetwatercreek.net /v2, re-armed it. Every click on the page
   landed on nothing. Craig, 2026-09-23: "now the page is frozen on SiteEdit unable
   to do anything". Measured with CDP on /v2/home after a save: display grid,
   opacity 0, pointer-events auto, and Exit SiteEdit hit-tested to this layer.
   (0,3,0) !important beats the (0,2,0) !important above. */
.toast.tlc-alert[hidden] { display: none !important; }
/* A LAYER THAT IS NOT `.on` IS FINISHED, SO IT TAKES NO CLICKS — held or not.
   `.toast.is-hold` above keeps pointer-events after the X removes `.on`, and
   Bootstrap 5.3 `.toast{pointer-events:auto}` re-arms a go veil wherever it loads
   after this sheet, so the fade (300ms in text-edit.js, forever in board-alert.js,
   whose X only removes `.on`) sat over the page and ate the next press. Measured
   2026-09-23 on sweetwatercreek.net /v2/home: Exit SiteEdit hit-tested to this
   layer for 280ms after every save. (0,3,0) beats both. */
.toast.tlc-alert:not(.on) { pointer-events: none; }
