/* =====================================================================
   sst-site-structure.css — TLC 5.0 SITE STRUCTURE, the SST container system.
   Split out of sst-styles.css 2026-09-02 15:58 MDT.

   WHY ITS OWN FILE. Only five sites link shared/core/v1/sst-styles.css
   (TurnerLee, MudCup, CraigWhitlock, EvolvedFastpitch, ElevatedMP). ColoradoLamb,
   EPIC4 and SweetwaterCreek are still on the older All-HeaderScripts.html chain and
   serve their own ~10,000-line css/t_tlc-styles.css instead. Craig 2026-09-02 asked
   for this system on those three, and the only two ways to get it there were to
   migrate their whole script chain or to copy the block — and a second copy is
   exactly what "NO MORE LOCAL Patches ... when we are using the SST" forbids.
   So it is ONE file, linked by every site, and sst-styles.css no longer carries it.

   LOAD IT LAST, AFTER the site's own sheet. On the TLC 5.0 chain that is after
   sst-styles.css in sst-css-styles.html; on the older chain it is after
   /Custom_css/t_tlc-custom.css in All-HeaderScripts.html. These rules are written to
   win on source order at equal specificity — put it earlier and a site's own
   .container @media ramp beats it and nothing appears to happen.

   Cache-bust: v{MAJOR}.{NNN}, +0.001, per site in whichever file links it.
   ===================================================================== */

/* =====================================================================
   TLC 5.0 · SITE STRUCTURE — ONE CONTAINER FOR EVERY BAND
   added 2026-09-02 10:13 MDT
   ---------------------------------------------------------------------
   Minor Nav · Main Nav · Page Nav · Content · Footer must share ONE inner
   box so their first and last items line up down the page. The BAND is a
   full-width block and paints its color edge to edge; the INNER box is
   this container. Nothing here breaks out with 100vw — the bands are
   already full width in flow (#header .fixed-top, #main, #sticky.bg-Footer
   all measured x=0 w=viewport), and a 100vw breakout scrolls the page
   sideways by the scrollbar width on a desktop with classic scrollbars.

   THREE MODES, set by a body class the Content Template emits:
     (none)         Default — 1350 / 80%. Byte-for-byte today's geometry.
     .tlc-w-hd      HD      — 1920, every band.
     .tlc-w-full    Full    — bands at HD, CONTENT at 5% side padding.

   WHY TOKENS AND NOT FIVE MORE MEDIA BLOCKS. The five blocks above set
   .container and .navbar .container per breakpoint. A body class cannot
   beat a @media block by specificity (@media adds none) without repeating
   all five. Custom properties are read at use time, so one declaration on
   <body> re-points every band at once and the breakpoint ramp is stated
   in exactly one place.

   --tlc-cmax IS NEVER LEFT UNDECLARED. `var(--x, fallback)` substitutes an
   EMPTY value when --x is declared-but-empty, which voids the declaration
   and inherits instead. Every mode below declares all three.
   ===================================================================== */
/* --tlc-cmax IS ALWAYS A LENGTH, NEVER `none`. The /ops sheet does arithmetic
   on it — `calc((100vw - var(--tlc-cmax)) / 2)` — and `calc(100vw - none)` is
   invalid, which drops the whole declaration silently. Below 576 a 1350px cap
   is unreachable anyway (width is 100% of a <576 viewport), so this is
   byte-identical in paint to the `none` it replaces. */
:root {
	--tlc-cw:   100%;
	--tlc-cmax: 1350px;
	--tlc-gut:  var(--bs-gutter-x, 1rem);
	/* THE FULL BOX'S SIDE PADDING, AS A TOKEN. Added 2026-09-02 22:10 MDT.
	   Declared here and consumed twice: by the body.tlc-w-full rule at the bottom of
	   this file, and by shared/pbs/v1/pbs.css, which has to re-declare the Full box on
	   .pb2-inner because .pb2-wrap is width:100vw and breaks out of #main > .container
	   entirely — so body.tlc-w-full can never reach the board. TWO CONSUMERS, ONE
	   DECLARATION: restate the formula in either file and they drift the first time
	   1920 moves.
	   A custom property is substituted at the element that USES it, so --tlc-cmax and
	   --tlc-gut resolve to whatever is inherited there — 1350/bs-gutter on a Default
	   page, 1920/clamp(10px,2.2vw,40px) under body.tlc-w-hd or .tlc-w-full.
	   BELOW ~2044px THIS EQUALS THE HD GUTTER EXACTLY, because min() takes the smaller
	   branch, which is what makes "HD until notes opens, then Full" a continuous move
	   rather than a jump. Declared with a real value and never left empty — see the
	   note above about var(--x, fallback) substituting an EMPTY value. */
	--tlc-full-pad: min(5vw, calc(max(0px, (100vw - var(--tlc-cmax, 1920px)) / 2) + var(--tlc-gut, clamp(10px, 2.2vw, 40px))));
}
@media (min-width: 576px)  { :root { --tlc-cw: 90%; --tlc-cmax:  768px; --tlc-gut: .75rem; } }
@media (min-width: 768px)  { :root { --tlc-cw: 90%; --tlc-cmax:  992px; } }
@media (min-width: 992px)  { :root { --tlc-cw: 85%; --tlc-cmax: 1200px; } }
@media (min-width: 1200px) { :root { --tlc-cw: 80%; --tlc-cmax: 1350px; } }

/* HD · FULL — one declaration on <body> (0,1,1) outranks the :root blocks
   above (0,1,0) at every width, and inherits into every band. 1920 is
   Craig's number, 2026-09-02; the /ops chrome's 1800 is superseded by it.
   The clamp gutter is the one already shipped on .nav-row-inner. */
body.tlc-w-hd,
body.tlc-w-full {
	--tlc-cw:   100%;
	--tlc-cmax: 1920px;
	--tlc-gut:  clamp(10px, 2.2vw, 40px);
}

/* THE CONTAINER ITSELF. `.navbar .container` is listed so this rule matches
   a nav container at (0,2,0) — the same specificity as the blocks above —
   and wins on source order. Drop it and every nav keeps the old width. */
.container,
.container-lg, .container-md, .container-sm, .container-xl, .container-xxl,
.navbar .container {
	width:      var(--tlc-cw);
	max-width:  var(--tlc-cmax);
	padding-left:  var(--tlc-gut);
	padding-right: var(--tlc-gut);
	margin-left:  auto;
	margin-right: auto;
}

/* THE MAIN-NAV MENU WAS A CONTAINER INSIDE A CONTAINER — 80% OF 80%.
   Header-Default.html:426 nests `.container.mainDrop` inside the nav's own
   `.container` at :404, and `.navbar .container` matches BOTH. Measured on
   /our-work at 1920 before this rule: minor nav, main nav, content and
   footer all ended at 1635; .mainDrop ended at 1523.8 and #MainDropdown at
   1498.8 — the nav links stopped 136.2px short of every other band.
   custom-ops-chrome.html:147 already did exactly this for /ops only; this
   promotes it to the shared sheet so every page gets it.
   (0,4,0) beats `.mainDrop{padding-right:25px}` below at (0,1,0). */
nav.bg-Main > .container > .container.mainDrop {
	width: 100%;
	max-width: none;
	padding-left: 0;
	padding-right: 0;
}

/* AND ITS OTHER HALF. `.mainDrop{padding-right:25px}` (below) was cancelled by
   `nav.main_menu{margin-right:-25px}` in sst-hfnav.css:1327 and :1337 (and -30px
   at :1315). Two declarations, one hack: zeroing the padding alone leaves the
   negative margin hanging the last menu item OUTSIDE its own container.
   Measured on /ops/dashboard @1920 with only the padding zeroed: every container's
   content edge 1880.0, and "Pay Now" painted at 1905.0 — 25px past the box it
   lives in, past the ribbon, past the footer.
   sst-hfnav.css loads BEFORE this file (sst-css-styles.html :78 then :79), and a
   @media block adds no specificity, so (0,4,2) here beats nav.main_menu at (0,1,1)
   on both counts. Retire the two together or not at all. */
nav.bg-Main > .container > .container.mainDrop nav.main_menu {
	margin-right: 0;
}

/* THE MINOR NAV'S FIRST ITEM WAS 25px INSIDE EVERY OTHER BAND.
   Header-Default.html:375 emits an empty <div class="left25pad"> ahead of
   Sign-In, and sst-styles.css:2720 gives it padding-left:25px. It is a spacer
   for a container that no longer needs spacing — every band now shares one box.
   Measured on /portal @1600 before this rule: minor nav / main nav / content /
   footer content edge all 173.2, and the first painted minor-nav item at 198.2.
   /ops was already correct only because custom-ops-chrome.html:180 hid this one
   div for .opsdash pages; that rule is now redundant and has been removed, so
   there is ONE declaration instead of a shared bug plus a local patch.
   Scoped to the header's own minor nav — .left25pad is a generic utility class
   and must keep working anywhere else it is used. */
nav.bg-Minor > .container > .left25pad { display: none; }

/* AND THE SIGN-IN BLOCK'S OWN 15px, WHICH IS THE SAME BUG WEARING A DIFFERENT CLASS.
   Sign-In.html:59 reads
     {% if style.MinorNavAlign == "Left" %}right15pad{% else %}left15pad{% endif %}
   and `style` is a DEAD object — it is never assigned anywhere in this estate, so
   style.MinorNavAlign is always null. The else branch therefore always wins and the
   block gets a LEFT inset, while Header-Default.html:373 tests
   `== "Left" or == null`, which is TRUE, and places it on the LEFT. Placed left,
   padded as if it were right-aligned. Measured cololamb.com/ops/dashboard @1600:
   every band's content edge 35.2, the sign-in icon at 50.2.
   TurnerLee's own Sign-In.html has the branch hard-coded to right15pad, which is why
   this only shows on the sites that still carry the conditional.

   :first-child is the whole gate — it says "this block is the leading item of the
   band", which is exactly when a left inset is wrong. A right-aligned minor nav puts
   the block last and keeps its padding. */
nav.bg-Minor > .container > #SignIn:first-child { padding-left: 0; }

/* =====================================================================
   OPERATIONS CONTEXT — the navs DISPLAY but they do not STICK.
   Craig 2026-09-02: "Minor & Main Nav (per ID Brand) still display, but are
   no longer sticky, PageNav for each Operations page will become the sticky
   ribbon at the top going edge-to-edge."
   `tlc-ctx-ops` is emitted by all-site-width.html on any /ops path, so it
   reaches all 54 /ops pages — including the 38 that carry no .opsdash and are
   therefore invisible to shared/ops/v2/ops-dashboard.css.
   ===================================================================== */

/* #header is `height:0` (sst-hfnav.css:1145, [id="header"] = (1,0,0)) because
   its only child was fixed and reserved no flow. Un-fix the child without this
   and the navs paint on top of the page content. (1,1,1) beats it. */
body.tlc-ctx-ops #header { height: auto; }

/* Bootstrap's .fixed-top is (0,1,0) and carries no !important, so (1,1,1) is
   enough. Its top/right/left become inert the moment position is static. */
body.tlc-ctx-ops #header .fixed-top { position: static; }

/* THE HEADER NOW RESERVES ITS OWN HEIGHT, so every compensator must go to zero.
   `!important` ONLY because the rule it must beat already has it:
   Header-Default.html:225 is `body{padding-top:calc(var(--header-height,120px)
   + 50px) !important}` — an !important declaration cannot be beaten by a
   non-important one at any specificity. */
body.tlc-ctx-ops { padding-top: 0 !important; }

/* ONE TOKEN RETIRES THE REST. --ws-hdr-offset is the measured height of
   .fixed-top, written to <html> at runtime by sst-ops-pagenav.html:575 and read
   by FOUR rules: the /ops body padding (ops-dashboard.css:261), the sticky
   PageNav's `top` (:638), custom-ops-chrome.html:107's .top-nav, and
   sst-form-tracker-nav.html. Declaring it on <body> re-points all four at once,
   and it is a different ELEMENT from the inline <html> value, so no specificity
   fight — the ribbon lands at top:0 and the body padding computes to 0. */
body.tlc-ctx-ops { --ws-hdr-offset: 0px; }

/* THE LAST MAIN-NAV ITEM'S OWN TRAILING GUTTER — the third half of the mainDrop hack.
   The two above retire .mainDrop's padding-right:25px and nav.main_menu's -25px margin.
   What is left is sst-hfnav.css:2412 `li.nav-item{padding:0 .1rem}` plus :1771
   `a.nav-link{padding:12px 6px}` — about 7.6px between the last link's text and the box
   those two just aligned it to. Measured @1920 /ops/dashboard: main nav "Pay Now" lands
   right=1880 = the container content edge WITH this rule; the minor nav's last item,
   which has no equivalent, sits at 1874.7. Operations context only — whether the PUBLIC
   nav's last item sits flush was the open question, and Craig answered it 2026-09-02:
   "yes flush the public nav too". So this is UNGATED — every page, every site linking this
   sheet, not just Operations context. Promoted from custom-ops-chrome.html:159. */
nav.bg-Main > .container > .container.mainDrop nav.main_menu > ul > li:last-child,
nav.bg-Main > .container > .container.mainDrop nav.main_menu > ul > li:last-child > a {
	padding-right: 0;
}

/* THE /ops FOOTER IS ONE 60px COPYRIGHT LINE. Craig 2026-09-01 09:20 MDT: "Ops: black bg
   Footer should be minimized to single Copyright line - NO LOGO (60px tall total),
   copyright centered vertically"; 11:05 MDT "footer doesn't match color" -> --color3, the
   token the main nav, the submenus and the /portal footer already paint from.

   THE MARKUP HALF IS Footer-Operations.html, selected by ID Settings item 20483 holding
   FooterLayout = "Operations"; it already drops the logo row. This is the HEIGHT half, and
   it belongs HERE and not in shared/ops/v2/ops-dashboard.css: that sheet is linked only on
   the 18 /ops pages carrying .opsdash, while FooterLayout reaches all 53
   (_notes/verify/ops-sweep-54.txt). body.tlc-ctx-ops is the same set as the footer layout,
   which is the entire point of gating on it. Promoted from custom-ops-chrome.html:221-262,
   where the identical rules reached 18 pages and left 35 with an unpinned footer.

   HEIGHT ON BOTH #sticky AND #footer: #sticky is the painted band, #footer the box holding
   the line, and .bg-Footer-image is out of flow — pin one alone and the other keeps its old
   height. That is why they measured the same 198.5px before any of this.
   background-color carries !important ONLY because sst-hfnav.css:76 already does.
   NO background-image declaration: the image lives on .bg-Footer-image, never on
   .bg-Footer, so the old `background-image:none !important` was targeting nothing. */
body.tlc-ctx-ops #sticky.bg-Footer {
	background-color: var(--color3, #414141) !important;
	height: 60px;
	min-height: 60px;
}
/* the whole LAYER, not an <img>: sst-hfnav.css:84-98 gives it border-top:3px solid
   var(--color1xl) and background-image:var(--FooterBgImage), position:absolute at 100%x100%.
   Hiding it is what takes both the art and the 3px rule out of the 60px band. */
body.tlc-ctx-ops #sticky .bg-Footer-image { display: none !important; }

/* ── THE /ops FOOTER IS NOT STICKY ───────────────────────────────────────────
   Craig, 2026-09-02: "scope it out of the shared file, /ops only".

   sst-styles.css:8933 makes EVERY footer on the estate
   `#sticky.bg-Footer{position:sticky !important; top:100vh !important}` — the
   classic push-the-footer-to-the-bottom trick. That rule is loaded by all ten
   sites and it STAYS; this opts /ops out of it and nothing else.

   WHY. A sticky box with top:100vh is the one out-of-flow band left on an /ops
   page — #header .fixed-top is already `position:static` here (line 151) — and
   it is the mechanism behind the report of the footer "floating up" with grey
   under it after repeated scroll direction changes. It only engages on a SHORT
   page: measured 2026-09-02, /ops/edit-organization scrollHeight 1064 against a
   900 viewport, while /ops/dashboard at 4300 never sticks at all. NOT
   reproducible headless — 26 wheel reversals at 1920x800 in Chromium AND WebKit,
   zero drift — so this removes the mechanism rather than fixing a measured
   failure, and it is written to be reverted in one hunk if it ever matters.

   min-height ON #wrapper, NOT display:flex ON body. Flexing body would make
   every in-flow child a flex item, and body has three: #wrapper, #sticky, and a
   stray 1466px-wide `div.row` that is 26px WIDER than a 1440 viewport and 0 tall.
   Today it overflows nothing because it has no height; as a flex item it would be
   stretched and shrunk by the cross axis, which is a layout change to something
   nobody asked about. The height arithmetic needs no flex: this footer is pinned
   to exactly 60px above, so a wrapper floor of 100vh - 60px puts the footer at
   the viewport bottom on a short page and below the fold on a long one, which is
   what the sticky rule was buying. Change the 60px in both places or neither. */
body.tlc-ctx-ops #wrapper { min-height: calc(100vh - 60px); }
body.tlc-ctx-ops #sticky.bg-Footer {
	position: static !important;
	top: auto !important;
}
/* [id="footer"] is (1,0,0) and NOT important at sst-hfnav.css:69, so (2,2,1) is enough and
   no !important is needed here. One flex box centers the line at any font size. The old
   local copy also carried `background:transparent`, a non-important shorthand losing to an
   !important longhand that already set it — inert, and dropped. */
body.tlc-ctx-ops #sticky #footer.footer {
	padding: 0;
	height: 60px;
	min-height: 60px;
	display: flex;
	align-items: center;
}

/* FULL — the CONTENT band only. Every other band stays at the HD box.

   FULL IS NEVER NARROWER THAN HD. Craig 2026-09-02: "we don't ever want 'HD' container
   outside of the 'full' container." A flat 5% breaks that below ~2044px: at 1440 the HD
   gutter is clamp(10px,2.2vw,40px) = 31.7px while 5% is 72px, so the HD bands stuck out
   PAST the Full content and Full read as the narrower of the two. min() takes whichever
   padding is smaller, so Full tracks HD exactly up to the crossover and only opens out
   beyond it — at 2560, HD pads 360px against Full's 128px.
   5vw not 5%: a percentage resolves against the containing block, and this box's parent
   is already inset. Same reason .opsdash uses vw. */
body.tlc-w-full #main > .container,
body.tlc-w-full main#main > .container {
	width: 100%;
	max-width: none;
	/* THE FORMULA MOVED TO --tlc-full-pad ON :root, unchanged, because pbs.css has to
	   apply the identical box to .pb2-inner and a second copy of these two lines is
	   exactly what goes stale. Computed value is byte-identical to what was here. */
	padding-left:  var(--tlc-full-pad);
	padding-right: var(--tlc-full-pad);
}
