@font-face {
  font-family: "SansPro";
  font-display: swap;
  src: url('https://d122f4822rob2u.cloudfront.net/fonts/SourceSansPro-Regular.ttf');;
}

@font-face {
  font-family: "SansProBold";
  font-display: swap;
  src: url('https://d122f4822rob2u.cloudfront.net/fonts/SourceSansPro-SemiBold.ttf');;
}

@font-face {
  font-family: "SansProLight";
  font-display: swap;
  src: url('https://d122f4822rob2u.cloudfront.net/fonts/SourceSansPro-ExtraLight.ttf');;
}

@font-face {
  font-family: "righteous";
  font-display: swap;
  src: url('https://d122f4822rob2u.cloudfront.net/fonts/Righteous-Regular.ttf');;
}

@font-face {
  font-family: "avenirBold";
  font-display: swap;
  src: url('https://d122f4822rob2u.cloudfront.net/fonts/Ubuntu-Medium.ttf');;
}





html{
  scroll-padding-top: 90px;
}

.boldBody{
  font-family: 'SansProBold', sans-serif;
  font-size: 1.1em;
}

.lightBody{
  font-family: 'SansPro', sans-serif;
  font-size: 1.05em;
}


.nav-link:hover{
  background-color: #e8edf2 !important; /* steel grey */
}

.navbar .nav-link.active {
  font-weight: normal !important; /* Prevent bold font on active link */
  background-color: #e8edf2 !important; /* steel grey */
}

.navbar .nav-item {
  font-weight: normal !important; /* Prevent bold font on active link */
}

.darkhover {
  -webkit-filter: brightness(100%);
  cursor: pointer;
}

.darkhover:hover {
  -webkit-filter: brightness(80%);
  filter: brightness(80%);
  -webkit-transition: all 1s ease;
  -moz-transition: all 1s ease;
  -o-transition: all 1s ease;
  -ms-transition: all 1s ease;
  transition: all 1s ease;
}

    .register_holder {
      display: flex;
      align-items: center;
      justify-content: center;
    }

.btn-outline-light:hover{
  color: black !important;
}

.btn-outline-light:focus{
  color: black !important;
}

.fixed_alert{
  position: fixed;
  top: 0px;
  left: 50%;
  transform: translate(-50%, 0%);
  width: 92%;
  animation: slidedown 0.2s 0.2s ease-out forwards;
}
@keyframes slidedown {
  to {
    top: 47px;
  }
}

  @media only screen and (min-width: 800px) {  
    .w400 {
      font-weight: 400;
      font-size: 1.6em;
    }  
  }

  @media only screen and (max-width: 800px) {  
    .w400 {
      font-weight: 400;
      font-size: 1.2em;
    }  
  }
  

  @media only screen and (min-width: 800px) {  
    .w300 {
      font-weight: 400;
      font-size: 1.4em;
    }  
  }

  @media only screen and (max-width: 800px) {  
    .w300 {
      font-weight: 400;
      font-size: 1.2em;
    }  
  }  


  @media only screen and (min-width: 800px) {     
    .w800 {
      font-weight: 800;
      font-size: 3.5em;
    }
  }

  @media only screen and (max-width: 800px) {     
    .w800 {
      font-weight: 800;
      font-size: 2.5em;
    }
  }


.white{
color:white;
}


.selected{
  background-color: #E5E4E4;
  border: 3px solid black;
}

.selected5{
  background: white !important;
  /* make button look selected */
  border: 1px solid black !important;
  color: black !important;
  /* shadow */
  box-shadow: 0 0 10px rgba(0,0,0,0.5);
}


.font-primary {
  background-image: linear-gradient(to right, var(--tw-gradient-stops));
  color: transparent; /* Make the text color transparent */
  background-clip: text; /* Clip the background to the text */
  -webkit-background-clip: text; /* For Safari */
  --tw-gradient-from: #9CACFF;
  --tw-gradient-to: rgb(214 173 255 / 0);
  --tw-gradient-stops: var(--tw-gradient-from), #D6ADFF, var(--tw-gradient-to);
  --tw-gradient-to: #D7B8FF;
}

.font-primary-darker {
  background-image: linear-gradient(to right, var(--tw-gradient-stops));
  color: transparent; /* Make the text color transparent */
  background-clip: text; /* Clip the background to the text */
  -webkit-background-clip: text; /* For Safari */
  --tw-gradient-from: #1a3a5c;
  --tw-gradient-to: rgb(46 109 164 / 0);
  --tw-gradient-stops: var(--tw-gradient-from), #2e6da4, var(--tw-gradient-to);
  --tw-gradient-to: #2e6da4;
}


.font-primary-dark{
  color: #1a3a5c !important;
}


.btn-primary {
  color: white;
  background-color: #1B5FA8;
  border: 1px solid #164D8A;
}

.text-primary {
  color: #1D4ED8 !important; /* mirror .btn-primary bg */
}


.btn-primary:hover {
  background-color: #164D8A;
  border: 1px solid #164D8A;
}


.btn-primary:focus{
  background-color: #164D8A;
  border: 1px solid #164D8A;
}

.btn-primary.disabled{
  background-color: rgb(88, 88, 88) !important;
  border: 1px solid black !important;
}

.btn-primary:disabled{
  background-color: rgb(88, 88, 88) !important;
  border: 1px solid black !important;
}


/* -----------------------------------------------------------
   OUTLINE VARIANT THAT VISUALLY MATCHES YOUR .btn-primary
   -----------------------------------------------------------*/

/* default (transparent background, coloured text/border) */
.btn-outline-primary {
  color: #1B5FA8;
  background-color: transparent;
  border: 1px solid #1a3a5c;
  border-radius: 4px;
}

/* hover / focus / active — match the filled style’s hover */
.btn-outline-primary:hover,
.btn-outline-primary:focus,
.btn-outline-primary:active,
.btn-outline-primary.active,
.btn-outline-primary.dropdown-toggle.show {
  color: #000;                 /* accessible contrast  */
  background-color: #e8edf2;   /* steel grey hover */
  border-color: #1a3a5c;
  text-decoration: none;       /* kill link underline in <a> buttons */
}

/* focus ring for keyboard users (Bootstrap normally handles this,
   but re-assert here in case your global CSS resets it) */
.btn-outline-primary:focus-visible {
  outline: 0;
  box-shadow: 0 0 0 0.25rem rgba(26, 58, 92, 0.25); /* 4 px focus halo */
}

/* disabled states (match your filled button’s grey) */
.btn-outline-primary:disabled,
.btn-outline-primary.disabled {
  color: rgb(88, 88, 88);     /* muted text for contrast */
  background-color: transparent;
  border-color: rgb(88, 88, 88);
  pointer-events: none;
  opacity: 0.65;              /* keeps parity with Bootstrap defaults */
}


.btn-outline-dark{
  background-color: white
}

.btn-outline-dark:hover{
  color:black !important;
  background-color: #e8edf2; /* steel grey */
  border: 1px solid black;
}





.form-control{
  border-color: black;
}

.form-select {
  text-align: center;
}

@media only screen and (min-width: 1200px) {
  .pt-10 {
    padding-top: 120px;
  }
}
@media only screen and (max-width: 1200px) {
  .pt-10 {
    padding-top: 30px;
  }
}


.results {
  max-width: 2000px;
}

footer {
  position: fixed;
  bottom: 0;
  width: 100%;
}

.viewportheight {
  min-height:87vh;
}

.predictorcolour {
 background-color: #f4f6f8;
}

.curveborder {
  border-radius: 10px;
}

.fade-in-slow2{
  -webkit-animation: 0.2s ease 0s normal forwards 1 fadein;
  animation: 0.2s ease 0s normal forwards 1 fadein;
  opacity:1
}

.fade-in-slow3{
  -webkit-animation: 1s ease 0s normal forwards 1 fadein;
  animation: 1s ease 0s normal forwards 1 fadein;
  opacity:1
}

@keyframes fadein{
  0% { opacity:0; }
  75% { opacity:0; }
  100% { opacity:1; }
}

@-webkit-keyframes fadein{
  0% { opacity:0; }
  75% { opacity:0; }
  100% { opacity:1; }
}

.fade-in-fast{
  -webkit-animation: 0.1s ease 0s normal forwards 1 fadein;
  animation: 0.1s ease 0s normal forwards 1 fadein;
  opacity:1
}

@keyframes fadein{
  0% { opacity:0; }
  33% { opacity:0; }
  100% { opacity:1; }
}

@-webkit-keyframes fadein{
  0% { opacity:0; }
  33% { opacity:0; }
  100% { opacity:1; }
}

.rotate {
  transition: 0.70s;
  -webkit-transition: 0.70s;
  -moz-transition: 0.70s;
  -ms-transition: 0.70s;
  -o-transition: 0.70s;
}
/*
.flash {
  animation-name: glowing;
  animation-duration: 0.2s; 
  animation-iteration-count: 1;
  animation-play-state: running; 
  animation-timing-function: ease-out; 
  animation-delay: 2.5s;
}



.flash1 {
  animation-name: glowing;
  animation-duration: 0.2s; 
  animation-iteration-count: 1;
  animation-play-state: running; 
  animation-timing-function: ease-out; 
  animation-delay: 2.6s;
}

.flash2 {
  animation-name: glowing;
  animation-duration: 0.2s; 
  animation-iteration-count: 1;
  animation-play-state: running; 
  animation-timing-function: ease-out; 
  animation-delay: 2.7s;
}

.flash3 {
  animation-name: glowing;
  animation-duration: 0.2s; 
  animation-iteration-count: 1;
  animation-play-state: running; 
  animation-timing-function: ease-out; 
  animation-delay: 2.8s;
}

.flash4 {
  animation-name: glowing;
  animation-duration: 0.2s; 
  animation-iteration-count: 1;
  animation-play-state: running; 
  animation-timing-function: ease-out; 
  animation-delay: 2.9s;
}

.flash5 {
  animation-name: glowing;
  animation-duration: 0.2s; 
  animation-iteration-count: 1;
  animation-play-state: running; 
  animation-timing-function: ease-out; 
  animation-delay: 0.1s;
}

.flash6 {
  animation-name: glowing;
  animation-duration: 0.2s; 
  animation-iteration-count: 1;
  animation-play-state: running; 
  animation-timing-function: ease-out; 
  animation-delay: 0.2s;
}

.flash7 {
  animation-name: glowing;
  animation-duration: 0.2s; 
  animation-iteration-count: 1;
  animation-play-state: running; 
  animation-timing-function: ease-out; 
  animation-delay: 0.3s;
}

.flash8 {
  animation-name: glowing;
  animation-duration: 0.2s; 
  animation-iteration-count: 1;
  animation-play-state: running; 
  animation-timing-function: ease-out; 
  animation-delay: 0.4s;
}
*/

.dropdown-menu {
  max-height: 400px;
  overflow-y: auto;
}

  .fade_in_fast{
    -webkit-animation: 0.5s ease 0s normal forwards 1 fadein;
    animation: 0.5s ease 0s normal forwards 1 fadein;
    opacity:1
  }

@media only screen and (max-width: 500px) {
  iframe[src*=youtube] {
    width: 330px;
    height: 200px;
  }
}

.initial_hidden{
  display: none;
}

a[type='button'] {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
}


.index_title{
  /* font family bold maven pro */
  font-family: 'avenirBold', sans-serif;
  letter-spacing: 0.02em;
}

/* Override inline-block styling for CKEditor */
.django-ckeditor-widget {
  display: block !important; /* Change to block */
  width: 100%;              /* Full width */
}





.canvas_align{
  position: absolute;
  top: 40%;
  left: 50%;
  transform: translate(-50%, -50%);               
}

/* For mobile devices */

/* .database_holder{
  min-height: 350px;
} */

b{
  font-family: 'SansProBold', sans-serif;
  font-size: 1em;
}

.visually-hidden {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}


@media (max-width: 992px) {
  /* Style for screens smaller than "lg" */
}

.modal-content{
  border-radius: 10px;
}

.card{
  border-radius: 10px;
}

.card-header{
  background: none;
  border-radius: 10px;
}

.card-footer{
  background: none;
  border-radius: 10px;
}

/* Add this if you want to differentiate user and AI messages */

.min-vh-100{
  min-height: calc(100vh - 52px) !important;
}

/* #titleholder {
  display: flex;
  align-items: flex-end;
  justify-content: center;
} */

@media (max-width: 1200px) { /* This corresponds to Bootstrap's 'md' breakpoint */
}


.bg_light_gradient {
  background: linear-gradient(300deg,#f5f5f5,#d3ced8,#e9e9e9);
  background-size: 180% 180%;
  animation: gradient-animation 24s ease infinite;
}

@keyframes gradient-animation {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}


/* if screensize is less then 800px then regs_list height is 3vh if greater than this then 60vh */



/* .btn-design-menu removed -- was only used by design_tools_card.html's
   vertical category menu, replaced by .dt-pill below. The bare `.btn:active`
   half of its old shared selector is sitewide (every Bootstrap button's
   active/pressed state), kept standalone so removing the dead class rule
   doesn't change that. */
.btn:active{
    background-color: #e3e2e0;
    color: #28242c;
    font-weight: bold;
}

/* ─── FREE DESIGN TOOLS (Phase 4 CalcForge-dashboard-pattern port) ───
   Light-mode pill switcher + compact icon+name tile grid for
   /free-civil-engineering-design-software (design_tools_card.html).
   Same layout shape as CalcForge's dashboard .cf-tool-pill/.cf-dash-tool-*
   (a different, dark-mode project) but built from this site's own tokens
   and .topic-chip pattern (blog/static/blog/blog-nav.css) rather than
   copying those dark values. */
.dt-panel{
  /* Extra bottom padding (was 22px all round) now that .dt-footnote is gone --
     the tile grid/rail is the last thing in the card, so it gets more breathing
     room instead of ending flush with the card edge. */
  background:#fff; border:1px solid var(--line); border-radius:18px; padding:22px 24px 40px;
}
/* Wraps .dt-panel on both hubs (estimating_hub.html, design_tools.html) --
   a plain class instead of Bootstrap's .pb-5 so this can be tuned per-page
   without fighting .pb-5's !important (see Feature-page Hero Backgrounds
   note in CLAUDE.md re: utility classes silently winning over overrides). */
.dt-tools-section{ padding-bottom:96px; }
/* Fold wrapper -- hero + tools section on both hubs (estimating_hub.html,
   design_tools.html). min-height, never height: on a narrow screen the tile
   grid drops to 1 column and the card grows taller than the fold, which must
   simply be allowed to happen -- this is a floor, not a cap. --fold-offset is
   the distance from the viewport top to this wrapper (the static .site-nav,
   plus the breadcrumb bar on the estimating hub only, since only that view
   passes `breadcrumbs` into context); each page sets its own value in its
   {% block extra_css %}. svh, not vh: on mobile vh measures the viewport with
   browser chrome retracted, which would push the FAQ further down than
   intended once the chrome reappears. */
.dt-fold{
  display:flex; flex-direction:column;
  min-height: calc(100vh  - var(--fold-offset, 62px));   /* fallback for no svh support */
  min-height: calc(100svh - var(--fold-offset, 62px));
}
.dt-fold > .dt-tools-section{ display:flex; flex-direction:column; flex:1 1 auto; }
/* .dt-panel must itself be a flex column, not just a flex-grown block, or
   its own child (.dt-panel-body) has no flex parent to stretch against --
   flex:1 1 auto on .dt-panel-body below would be inert and the extra height
   would just sit as blank space under .dt-panel-body, inside .dt-panel's own
   box, never reaching the rail/tile-grid at all. */
.dt-fold > .dt-tools-section > .dt-panel{ display:flex; flex-direction:column; flex:1 1 auto; }
/* Stretch the rail's vertical divider the full card height so the empty
   space below a short category's tiles reads as intentional sidebar space,
   not a layout gap. Scoped to .dt-fold so .dt-panel-body's default
   align-items:start (below) is untouched anywhere else it's used. Tiles stay
   top-aligned at their natural height -- only the rail and its border-right
   stretch, never .dt-tile-grid's rows. */
/* align-content:stretch grows the grid's single row track itself to fill
   .dt-panel-body's flex-grown height -- align-items:stretch alone only
   stretches .dt-rail/.dt-tile-grid to that row's natural (content) height,
   which would leave the extra space sitting unfilled below the row instead
   of reaching the rail/divider. */
.dt-fold .dt-panel-body{ flex:1 1 auto; align-items:stretch; align-content:stretch; }
.dt-panel-head{ display:flex; align-items:center; justify-content:space-between; gap:16px; flex-wrap:wrap; margin-bottom:16px; }
.dt-panel-head h2{ margin:0; }
.dt-tool-count{
  font-family:'IBM Plex Mono',monospace; font-size:11px; letter-spacing:0.06em; text-transform:uppercase;
  color:var(--mute); background:var(--bg-2); border-radius:999px; padding:4px 12px; white-space:nowrap;
}
/* Category rail (category rail redesign, Free Tools Pages.dc.html design
   import) -- replaces .dt-pill-row/.dt-pill on both hubs. .dt-panel-body
   is the 216px-rail / flexible-grid layout; the rail itself is a plain
   vertical nav, active item highlighted with an inset left bar matching
   the accent-underline convention used elsewhere (e.g. the estimating-tool
   mode toggle's .selected state). This is one of two .dt-* media queries in
   this codebase (the other, just below, steps the tile grid down from 3 to
   2 to 1 columns) -- below ~768px the rail collapses to a horizontal
   wrapping row above the grid instead of a left column, since a fixed
   216px column doesn't have room at that width. */
.dt-panel-body{ display:grid; grid-template-columns:216px 1fr; gap:24px; align-items:start; }
/* border-right (rather than a plain border) would run flush from the very
   top to the very bottom of the stretched .dt-fold rail -- the ::after
   pseudo-element below is inset top/bottom instead, so the divider reads as
   a deliberate rule inside the card, not an edge-to-edge column boundary. */
.dt-rail{ position:relative; display:flex; flex-direction:column; gap:2px; padding-right:20px; }
.dt-rail::after{ content:""; position:absolute; top:6px; bottom:6px; right:0; width:1px; background:var(--line); }
.dt-rail-eyebrow{
  font-family:'IBM Plex Mono',monospace; font-size:10px; letter-spacing:0.14em; text-transform:uppercase;
  color:var(--mute); padding:2px 10px 10px;
}
.dt-rail-item{
  display:flex; align-items:center; justify-content:space-between; gap:10px; width:100%; text-align:left;
  cursor:pointer; border:0; background:transparent; border-radius:8px; padding:9px 10px;
  font-family:'IBM Plex Sans',system-ui,sans-serif; font-size:13.5px; font-weight:500; color:var(--ink-2);
  transition:background .15s, color .15s;
}
.dt-rail-item:hover{ background:rgba(27,95,168,.04); }
.dt-rail-item.selected{ background:rgba(27,95,168,.08); color:var(--accent); font-weight:600; }
.dt-rail-count{ font-family:'IBM Plex Mono',monospace; font-size:10.5px; color:var(--mute); }
.dt-rail-item.selected .dt-rail-count{ color:var(--accent); }
.dt-tile-grid{ display:grid; grid-template-columns:repeat(3, minmax(0, 1fr)); gap:10px; align-content:start; }
@media (max-width:767.98px){
  .dt-panel-body{ grid-template-columns:1fr; }
  .dt-rail{ flex-direction:row; flex-wrap:wrap; gap:6px; border-bottom:1px solid var(--line); padding:0 0 14px; }
  .dt-rail::after{ display:none; }
  .dt-rail-eyebrow{ display:none; }
  .dt-rail-item{ width:auto; border:1px solid var(--line); border-radius:999px; padding:7px 14px; }
  .dt-rail-item.selected{ border-color:var(--accent); }
  .dt-tile-grid{ grid-template-columns:repeat(2, minmax(0, 1fr)); }
  /* Rail is now a horizontal pill row above the grid, not a left column --
     the full-height stretch above only makes sense for the two-column
     desktop layout. */
  .dt-fold .dt-panel-body{ align-items:start; }
}
@media (max-width:479.98px){
  .dt-tile-grid{ grid-template-columns:1fr; }
}
.dt-tile{
  display:flex; align-items:center; gap:11px; background:var(--bg); border:1px solid var(--line);
  border-radius:11px; padding:12px 13px; text-decoration:none; color:inherit; transition:background .15s, border-color .15s;
  min-height:75px;
}
.dt-tile:hover{ background:rgba(27,95,168,.06); border-color:var(--accent); color:inherit; }
.dt-tile-icon{
  flex:none; width:34px; height:34px; border-radius:9px; background:var(--bg-2);
  display:flex; align-items:center; justify-content:center;
}
.dt-tile-icon img{ width:18px; height:18px; }
.dt-tile-name{ flex:1; min-width:0; font-size:13.5px; font-weight:600; color:var(--navy); line-height:1.25; }

/* Per-category AI-bridge CTA tile (design import, Free Tools Pages.dc.html
   round 2) -- the last tile in each category's grid on both hubs, replacing
   the single generic band that used to sit below the whole tools card
   (estimating hub's video band, design hub's .dt-learn card -- both removed).
   A .dt-tile modifier, not a separate component: reuses .dt-tile's box/flex/
   gap/radius/padding. Was a solid navy tile with a "Civils.ai · paid" /
   "CalcForge · course" kicker line and a trailing arrow -- now styled like
   every other tile (same background/border/text/icon-badge colour, no
   arrow) so it doesn't read as a jarring block in the grid, with a small
   accent "Premium" badge in the corner carrying the same signal the kicker
   used to. .dt-tile-cta-icon only exists to colour the Font Awesome glyph
   (var(--accent), matching the site's other icon-in-circle pattern, e.g.
   the nav dropdown's .dd-ico) -- every other tile's icon is a pre-coloured
   img with nothing to tint. */
.dt-tile-cta{ position:relative; }
.dt-tile-cta-icon{ color:var(--accent); }
.dt-tile-cta-copy{ flex:1; min-width:0; display:flex; flex-direction:column; }
.dt-tile-cta-label{ font-size:13.5px; font-weight:600; color:var(--navy); line-height:1.25; }
.dt-tile-cta-badge{
  position:absolute; top:8px; right:9px;
  font-family:'IBM Plex Mono',monospace; font-size:8.5px; letter-spacing:0.08em; text-transform:uppercase;
  color:#fff; background:var(--accent); border-radius:999px; padding:2px 8px; line-height:1.4;
}




.li-cross {
  position: relative;
  padding-left: 1.5em;  /* space to preserve indentation on wrap */
}

.li-cross::before{
  content: "✗";
  position: absolute;
  left: 0;
  color: red;
  
}


body {
  max-width: 100vw;
}

.form-check-input:checked {

  background-color: #1a3a5c;
  border-color: #000;
}

.spinner-border{
  overflow: hidden;
}

strong{
  font-family: 'SansProBold', sans-serif;
  font-size: 1.1em;
}

a{
  color: #1a3a5c
}

.bg_dark_gradient{
  background: rgb(35,37,37);
  background: linear-gradient(135deg, rgba(35,37,37,1) 0%, rgba(39,39,39,1) 100%);
  border: 1px solid rgb(70, 70, 70);
}

.card-hover-animation:hover {
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); /* Add shadow */
  background-color: #e8edf2 !important;
}

/* ===== MODERN ANIMATIONS ===== */

/* ---- Hero section ---- */
.hero-badge {
  display: inline-block;
  font-size: 0.8rem;
  font-weight: 500;
  color: #1B5FA8;
  background: rgba(27, 95, 168, 0.08);
  border: 1px solid rgba(27, 95, 168, 0.2);
  border-radius: 999px;
  padding: 0.3rem 0.85rem;
  letter-spacing: 0.01em;
}

.hero-highlight {
  color: #1B5FA8;
  position: relative;
}
.hero-highlight::after {
  content: '';
  position: absolute;
  bottom: -3px; left: 0; right: 0;
  height: 3px;
  background: #1B5FA8;
  border-radius: 2px;
  opacity: 0.5;
}

.hero-chip {
  display: inline-block;
  font-size: 0.78rem;
  color: #495057;
  background: #fff;
  border: 1px solid #dee2e6;
  border-radius: 999px;
  padding: 0.25rem 0.75rem;
}

.hero-video-glow {
  box-shadow: 0 8px 40px rgba(27, 95, 168, 0.16), 0 2px 12px rgba(0, 0, 0, 0.06);
}

.btn-outline-secondary {
  border-radius: 8px !important;
}

/* Card hover lift */
.card-lift {
  transition: transform 0.22s ease, box-shadow 0.22s ease;
}
.card-lift:hover {
  transform: translateY(-5px);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12) !important;
}

/* Typewriter cursor */
.txt-rotate > .wrap {
  border-right: 2px solid #1B5FA8;
  padding-right: 2px;
  animation: blink-cursor 0.7s step-end infinite;
}
@keyframes blink-cursor {
  0%, 100% { border-color: #1B5FA8; }
  50%       { border-color: transparent; }
}


.background1{
  background-color: #f4f4f2;
}

html{
  font-family: 'SansPro', system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-size: 1.1em;
  line-height: 1.65;
}

h2, h3 {
  font-weight: 600;
  line-height: 1.3;
}

.pricing{
  font-size: 0.9em !important;
}

/* CSS for making all table columns equal width */
table.equal-width-columns th, 
table.equal-width-columns td {
  width: 25%; /* Divide the table width equally among 4 columns */
}

/* Optional: Ensure table layout is fixed to respect the width */
table.equal-width-columns {
  table-layout: fixed;
  width: 100%; /* Ensure the table spans the full container width */
}

.btn-outline-purple{
  border: 1px solid #1a3a5c !important;
}

.dropdown-menu-center {
  left: 50% !important;
  right: auto !important;
  text-align: center !important;
  transform: translate(-50%, 0) !important;
}


.btn-group .btn {
  font-weight: normal;
  text-decoration: none;
  color: black;
  background: none;
  border: none; /* Remove all borders initially */
}

.btn-group .btn-check:checked + .btn {
  font-weight: bold;
  color: black;
  background: none;
  border-bottom: 3px solid black !important; /* Force thicker black border */
}

.btn-group .btn-outline-primary {
  border: none; /* Remove Bootstrap's outline styles */
  border-radius: 0px;
  padding-left: 25px;
  padding-right: 25px;

}


.category-red{
  background-color: #FDEBEC;
}

.category-grey{
  background-color: #F1F1EF;
}

.category-blue{
  background-color: #E9F3F7;
}

.category-brown{
  background-color: #F3EEEE;
}

.category-green{
  background-color: #EDF3EC
}

.workflow-card{
  cursor: pointer;
  text-decoration: none;
}

.workflow-card:hover{
  border-color: black;
  /* background-color: #eeefff; */
}

.workflow-card:hover .card-header{
  background-color: #e8edf2 !important;
}

.badge-rotate {
  display: inline-block;
  opacity: 1;
  transition: opacity 0.5s ease-in-out;
}

.badge-rotate.hide {
  opacity: 0;
}


.check-list {
  list-style: none; /* Remove default bullets */
  margin: 0;
  padding: 0;
}

.check-list li {
  position: relative;
  margin-bottom: 0.5em;
  padding-left: 1.5em;      /* Space for the icon */
  line-height: 1.3;         /* Slightly increase line spacing */
}

/* Use Font Awesome’s “content” for the check icon */
.check-list li::before {
  font-family: "Font Awesome 5 Free"; /* Adjust if you use another FA version/name */
  content: "\f00c";                  /* \f00c is the "check" icon */
  font-weight: 900;                  /* Solid icon weight (fa-solid) */
  color: #4CAF50;                    /* Green color—customize as needed */
  position: absolute;
  left: 0;
  top: 0;                            /* Align near the top of the line */
  font-size: 1.2em;                  /* Make the icon larger/bolder */
}


.marquee {
  --gap: 2rem;
  display: flex;
  overflow: hidden;
  user-select: none;
  gap: var(--gap);
}

.marquee__content,
.marquee__content2 {
  flex-shrink: 0;
  display: flex;
  justify-content: space-around;
  min-width: 100%;
  gap: var(--gap);
  animation: scroll 38s linear infinite;
}

.marquee__content img,
.marquee__content2 img {
  width: 160px;
  filter: grayscale(100%);
  opacity: 0.55;
  transition: filter 0.3s ease, opacity 0.3s ease;
}

.marquee__content img:hover,
.marquee__content2 img:hover {
  filter: grayscale(0%);
  opacity: 1;
}

.marquee__content li,
.marquee__content2 li {
  list-style: none;
}

.marquee-outer {
  position: relative;
}

.marquee-outer::before,
.marquee-outer::after {
  content: '';
  position: absolute;
  top: 0; bottom: 0;
  width: 100px;
  z-index: 2;
  pointer-events: none;
}

.marquee-outer::before {
  left: 0;
  background: linear-gradient(to right, #F7F6F3 0%, transparent 100%);
}

.marquee-outer::after {
  right: 0;
  background: linear-gradient(to left, #F7F6F3 0%, transparent 100%);
}

.bg-light .marquee-outer::before {
  background: linear-gradient(to right, #f8f9fa 0%, transparent 100%);
}

.bg-light .marquee-outer::after {
  background: linear-gradient(to left, #f8f9fa 0%, transparent 100%);
}

@keyframes scroll {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(calc(-100% - var(--gap)));
  }
}

.youtube2 {
  position: relative;
  padding-bottom: 65%; /* matches embedded video aspect ratio */
  height: 0;
}

.youtube2 iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border: 0;
}


#compare-civils-chatgpt .py-6 { padding-top: 3.5rem !important; padding-bottom: 3.5rem !important; }
  #compare-civils-chatgpt .py-7 { padding-top: 4.5rem !important; padding-bottom: 4.5rem !important; }

  #compare-civils-chatgpt .bg-gradient-primary {
    background-image: linear-gradient(135deg, #1a3a5c 0%, #2e6da4 100%);
  }
  #compare-civils-chatgpt .bg-gradient-dark {
    background-image: linear-gradient(135deg, #111 0%, #444 100%);
  }
  #compare-civils-chatgpt .brand-dot {
    width: 36px; height: 36px; border-radius: 12px;
    box-shadow: 0 6px 16px rgba(0,0,0,0.15);
  }

  #compare-civils-chatgpt .table > :not(caption) > * > * {
    padding-top: .95rem; padding-bottom: .95rem;
  }

  #compare-civils-chatgpt .table-section td {
    background: rgba(0,0,0,.02);
    font-size: .8rem;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: #6c757d;
    font-weight: 600;
  }
  #compare-civils-chatgpt .section-label::before{
    content: "";
    display: inline-block;
    width: .5rem; height: .5rem;
    background: #1a3a5c; border-radius: 50%;
    margin-right: .5rem; vertical-align: middle;
    box-shadow: 0 0 0 3px rgba(26,58,92,.15);
  }

  /* Subtle “soft” badges using Bootstrap vars where available */
  #compare-civils-chatgpt .bg-primary-subtle { background-color: rgba(13,110,253,.12) !important; color: #0d6efd !important; }
  #compare-civils-chatgpt .bg-success-subtle { background-color: rgba(25,135,84,.12) !important; color: #198754 !important; }
  #compare-civils-chatgpt .bg-secondary-subtle { background-color: rgba(108,117,125,.12) !important; color: #6c757d !important; }
  #compare-civils-chatgpt .bg-dark-subtle { background-color: rgba(33,37,41,.08) !important; color: #212529 !important; }
  #compare-civils-chatgpt .bg-body-tertiary { background-color: rgba(0,0,0,.03) !important; }

/* ════════════════════════════════════════════════════════════════════════════
   DESIGN SYSTEM ("Direction B" / Steel-blue editorial)
   Shared across: index.html, about.html, cad_ai.html, geotech_ai.html,
   workflow_specs_search.html. Page-specific overrides remain in each
   template's {% block extra_css %}.
   ════════════════════════════════════════════════════════════════════════════ */

/* ─── Palette tokens ─────────────────────────────────────────────────────── */
:root{
  --bg:#f4f4f2; --bg-2:#e9e8e3;
  --ink:#1a1a1a; --ink-2:#3a3733; --mute:#7a766e; --line:#d8d6cf;
  --navy:#1a1a1a; --navy-2:#2e2c28;
  --accent:#1B5FA8; --accent-2:#154a85;
  --orange:var(--accent); --orange-2:var(--accent-2);
  --ok:#16a34a;
  --bs-body-bg: var(--bg);
  --bs-body-color: #0e1116;
  --bs-body-font-family: 'IBM Plex Sans', system-ui, sans-serif;
  --bs-border-color: var(--line);
}

/* ─── Container width override ───────────────────────────────────────────
   Bootstrap 5.3 caps .container-xxl (and friends) at 1320px starting at
   the xxl breakpoint (≥1400px). We bump that to 1440px so wide-desktop
   displays use the full editorial canvas the templates were designed
   against. The trigger MUST be 1400px (not 1440) — at 1400-1439px the
   Bootstrap cap would otherwise still squeeze content to 1320 and the
   hero H1 wraps onto an extra line. */
@media (min-width: 1400px){
  .container,
  .container-sm,
  .container-md,
  .container-lg,
  .container-xl,
  .container-xxl{ max-width:1440px; }
}

.design-b{ font-family:'IBM Plex Sans', system-ui, sans-serif; font-size:15px; line-height:1.55; color:#0e1116; background:var(--bg); }
.design-b ::selection{ background:var(--accent); color:#fff; }
.design-b a{ color:inherit; text-decoration:none; }

/* ─── Type system ────────────────────────────────────────────────────────── */
.ff-display{ font-family:'Saira Semi Condensed',sans-serif; text-transform:uppercase; letter-spacing:-0.01em; }
.ff-mono   { font-family:'IBM Plex Mono',monospace; }
.display-h1{ font-family:'Saira Semi Condensed',sans-serif; font-weight:700; font-size:62px; line-height:1.05; letter-spacing:-0.01em; color:var(--navy); text-transform:uppercase; }
.display-h2{ font-family:'Saira Semi Condensed',sans-serif; font-weight:700; font-size:56px; line-height:1.03; letter-spacing:-0.015em; color:var(--navy); text-transform:uppercase; margin:0; }
.display-h3{ font-family:'Saira Semi Condensed',sans-serif; font-weight:700; font-size:30px; line-height:1.08; color:var(--navy); text-transform:uppercase; }
/* Subtle vertical gradient on em-highlighted words. Lifted accent at the
   top, full accent at the bottom — reads cleanly on the cream body bg and
   on the dark navy bands (.uc.primary, .edit-band, .sec-final). Falls back
   to solid accent in browsers without background-clip:text. */
.display-h1 em, .display-h2 em, .display-h3 em{
  font-style:normal; font-weight:800;
  background:linear-gradient(180deg, color-mix(in srgb, var(--accent) 70%, #fff), var(--accent));
  -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent;
  color:var(--accent);
}
.lede{ font-size:17px; color:var(--ink-2); max-width:56ch; }

.kicker{ font-family:'IBM Plex Mono',monospace; font-size:12px; letter-spacing:0.04em; color:var(--accent); font-weight:500; display:flex; align-items:center; gap:10px; }
.kicker::before{ content:""; width:24px; height:1px; background:var(--accent); }
.kicker-line{ font-family:'IBM Plex Mono',monospace; font-size:12px; color:var(--navy); letter-spacing:0.06em; display:flex; align-items:center; gap:12px; }
.kicker-line::before{ content:""; width:32px; height:1px; background:var(--navy); }

/* ─── Buttons ────────────────────────────────────────────────────────────── */
.design-b .btn-navy{ background:var(--navy); color:#fff; border:0; padding:16px 28px; border-radius:4px; font-weight:600; font-size:13px; letter-spacing:0.06em; text-transform:uppercase; display:inline-flex; align-items:center; gap:10px; }
.design-b .btn-navy:hover{ background:#000; color:#fff; }
.design-b .btn-orange{ background:var(--orange); color:#fff; border:0; padding:20px 36px; border-radius:4px; font-weight:600; font-size:14px; letter-spacing:0.06em; text-transform:uppercase; display:inline-flex; align-items:center; gap:10px; }
.design-b .btn-orange:hover{ background:var(--orange-2); color:#fff; }
.design-b .btn-accent{ background:var(--accent); color:#fff; border:0; padding:18px 32px; border-radius:4px; font-weight:600; font-size:13px; letter-spacing:0.06em; text-transform:uppercase; display:inline-flex; align-items:center; justify-content:center; gap:10px; transition:background .15s; }
.design-b .btn-accent:hover{ background:var(--accent-2); color:#fff; }
.design-b .btn-outline-navy{ border:1.5px solid var(--navy); color:var(--navy); background:transparent; padding:12px 20px; border-radius:4px; font-family:'IBM Plex Mono',monospace; font-size:12px; letter-spacing:0.04em; text-transform:uppercase; font-weight:500; display:inline-flex; align-items:center; gap:10px; }
.design-b .btn-outline-navy:hover{ background:var(--navy); color:#fff; }
.design-b .uc.primary .btn-outline-navy{ border-color:rgba(255,255,255,.5); color:#fff; }
.design-b .uc.primary .btn-outline-navy:hover{ background:#fff; color:var(--navy); border-color:#fff; }

/* ─── Hero video frame (used on homepage hero + geotech borehole image) ─── */
.hero-video{ position:relative; border-radius:16px; overflow:hidden; background:var(--navy); box-shadow:0 40px 80px -30px rgba(11,42,72,.35); }
.hero-video video, .hero-video img{ width:100%; height:auto; display:block; }
.corner-tag{ position:absolute; top:16px; left:16px; background:rgba(11,42,72,.88); color:#fff; font-family:'IBM Plex Mono',monospace; font-size:11px; padding:6px 10px; border-radius:4px; display:flex; align-items:center; gap:8px; }
.dot-live{ width:6px; height:6px; background:var(--orange); border-radius:50%; }

/* ─── Feature-page hero (cad_ai, geotech_ai, workflow_specs_search) ─────── */
.feature-hero{ position:relative; padding:0 16px; background:var(--bg); }
@media (max-width: 991.98px){ .feature-hero{ padding:0 16px; } }
.fh-eyebrow{ font-family:'IBM Plex Mono',monospace; font-size:11px; letter-spacing:0.18em; color:var(--accent); text-transform:uppercase; display:inline-flex; align-items:center; gap:14px; padding:24px 0 0; }
.fh-eyebrow::before, .fh-eyebrow::after{ content:""; width:14px; height:1px; background:var(--accent); display:inline-block; }
.fh-meta-row{ display:flex; align-items:center; justify-content:space-between; padding:16px 0 36px; border-bottom:1px solid var(--line); margin-bottom:48px; flex-wrap:wrap; gap:16px; }
.fh-meta-row .lhs{ font-family:'Saira Semi Condensed',sans-serif; font-weight:700; font-size:13px; letter-spacing:0.06em; color:var(--mute); text-transform:uppercase; }
.fh-meta-row .lhs b{ color:var(--navy); }
.fh-exhibit{ position:relative; padding:14px; background:#fff; border:1px solid var(--line); border-radius:14px; box-shadow:0 30px 60px -28px rgba(11,42,72,.18); }
.fh-exhibit-head{ display:flex; align-items:center; justify-content:space-between; padding:0 4px 12px; flex-wrap:wrap; gap:8px; }
.fh-exhibit-frame{ font-family:'IBM Plex Mono',monospace; font-size:10.5px; letter-spacing:0.14em; color:var(--mute); text-transform:uppercase; }
.fh-exhibit-frame b{ color:var(--navy); font-weight:600; }
.fh-exhibit-cap{ font-family:'IBM Plex Mono',monospace; font-size:10.5px; letter-spacing:0.06em; color:var(--mute); }
.fh-exhibit-cap .dot{ width:5px; height:5px; background:#10b981; border-radius:50%; display:inline-block; margin-right:6px; vertical-align:middle; box-shadow:0 0 0 3px rgba(16,185,129,.18); }
.fh-exhibit-video{ position:relative; border-radius:8px; overflow:hidden; background:#000; }
.fh-exhibit-video video, .fh-exhibit-video img{ width:100%; height:auto; display:block; }

/* ─── Feature-hero dark variant ─────────────────────────────────────────── */
.feature-hero--dark{ background:transparent; border-top-color:rgba(255,255,255,.15); isolation:isolate; }
.feature-hero--dark::before{
  content:"";
  position:absolute; left:50%; top:0;
  transform:translateX(-50%);
  width:100vw; height:100%;
  background:var(--navy);
  z-index:-1;
}
.feature-hero--dark .display-h1{ color:#fff; }
.feature-hero--dark .display-h1 em{ background:linear-gradient(180deg,#82b0d8,#5f93c7); -webkit-background-clip:text; background-clip:text; -webkit-text-fill-color:transparent; }
.feature-hero--dark .lede{ color:rgba(255,255,255,.65); }
.feature-hero--dark .fh-eyebrow{ color:#5f93c7; }
.feature-hero--dark .fh-eyebrow::before,
.feature-hero--dark .fh-eyebrow::after{ background:#5f93c7; }
.feature-hero--dark .btn-navy{ background:#fff; color:var(--navy); box-shadow:0 12px 28px -16px rgba(0,0,0,.5); }
.feature-hero--dark .btn-outline-navy{ border-color:rgba(255,255,255,.35); color:#fff; }
.feature-hero--dark .btn-outline-navy:hover{ background:rgba(255,255,255,.08); border-color:rgba(255,255,255,.6); }

/* ─── Use-case cards ─────────────────────────────────────────────────────── */
.uc{ background:#fff; border:1px solid var(--line); border-radius:20px; padding:36px; height:100%; display:flex; flex-direction:column; }
.uc.primary{ background:var(--navy); border-color:var(--navy); color:#fff; }
.uc.primary .display-h3{ color:#fff; }
.uc.primary .lede, .uc.primary p{ color:rgba(255,255,255,.78); }
.uc-num{ font-family:'IBM Plex Mono',monospace; font-size:13px; color:var(--accent); }
.uc-tag{ font-family:'IBM Plex Mono',monospace; font-size:11px; letter-spacing:0.04em; text-transform:uppercase; color:var(--mute); padding-left:14px; border-left:1px solid var(--line); }
.uc.primary .uc-tag{ color:rgba(255,255,255,.55); border-left-color:rgba(255,255,255,.15); }
.uc-bullets{ list-style:none; padding:0; margin:0 0 28px; }
.uc-bullets li{ display:flex; gap:12px; padding:8px 0; font-size:14px; color:var(--ink-2); }
.uc.primary .uc-bullets li{ color:rgba(255,255,255,.8); }
.uc-bullets li i{ color:var(--accent); font-size:12px; margin-top:6px; }
.uc-bullets li b{ color:var(--navy); font-weight:600; }
.uc.primary .uc-bullets li b{ color:#fff; }
.uc-video{ position:relative; border-radius:12px; overflow:hidden; background:#000; aspect-ratio:16/10; box-shadow:0 20px 50px -25px rgba(0,0,0,.3); }
.uc-video video{ width:100%; height:100%; display:block; object-fit:cover; }
.overlay-tag{ position:absolute; top:14px; left:14px; background:rgba(11,42,72,.92); color:#fff; font-family:'IBM Plex Mono',monospace; font-size:10px; letter-spacing:0.04em; padding:5px 10px; border-radius:3px; text-transform:uppercase; z-index:2; }
.uc.primary .overlay-tag{ background:rgba(201,125,46,.92); }

/* ─── Edit / export band ─────────────────────────────────────────────────── */
.edit-band{ background:var(--navy); color:#fff; border-radius:24px; padding:48px; }
@media (max-width: 991.98px){ .edit-band{ padding:32px; } }
.edit-band .display-h2{ color:#fff; }
.edit-band .display-h2 em{ color:var(--accent); }
.edit-band p{ color:rgba(255,255,255,.78); }
.edit-band ul{ list-style:none; padding:0; margin:0 0 28px; }
.edit-band ul li{ display:flex; gap:12px; padding:8px 0; font-size:14px; color:rgba(255,255,255,.85); align-items:flex-start; }
.edit-band ul li i{ color:var(--accent); margin-top:5px; font-size:11px; }
.edit-band .uc-video{ box-shadow:0 30px 60px -25px rgba(0,0,0,.6); }

/* ─── How-it-works steps ─────────────────────────────────────────────────── */
.step{ background:#fff; border:1px solid var(--line); border-radius:16px; overflow:hidden; height:100%; position:relative; display:flex; flex-direction:column; }
.step-n{ position:absolute; top:16px; left:16px; z-index:2; background:var(--navy); color:#fff; font-family:'Saira Semi Condensed',sans-serif; font-weight:700; font-size:14px; padding:6px 12px; border-radius:3px; letter-spacing:0.04em; }
.step-img{ aspect-ratio:16/10; background:var(--bg-2); overflow:hidden; }
.step-img img{ width:100%; height:100%; object-fit:contain; }
.step h4{ font-family:'Saira Semi Condensed',sans-serif; font-weight:700; font-size:20px; text-transform:uppercase; color:var(--navy); margin:20px 24px 10px; }
.step p{ margin:0 24px 24px; font-size:14px; color:var(--ink-2); }

/* ─── Why-teams-switch / testimonials surface ────────────────────────────── */
.sec-testimonials{ background:var(--bg-2); }
.why{ background:#fff; border:1px solid var(--line); border-radius:18px; overflow:hidden; height:100%; display:flex; flex-direction:column; }
.why.dark{ background:var(--navy); border-color:var(--navy); color:#fff; }
.why-img{ aspect-ratio:16/10; background:var(--bg-2); overflow:hidden; }
.why-img img, .why-img video{ width:100%; height:100%; object-fit:cover; display:block; }
.why.dark .why-img{ background:#000; }
.why-body{ padding:24px 26px 28px; display:flex; flex-direction:column; gap:12px; flex:1; }
.why-body h4{ font-family:'Saira Semi Condensed',sans-serif; font-weight:700; font-size:20px; text-transform:uppercase; color:var(--navy); margin:0; line-height:1.15; }
.why.dark .why-body h4{ color:#fff; }
.why-body p{ font-size:14px; color:var(--ink-2); margin:0; }
.why.dark .why-body p{ color:rgba(255,255,255,.78); }
.why-body ul{ list-style:none; padding:0; margin:0; display:flex; flex-direction:column; gap:6px; }
.why-body ul li{ font-size:13px; color:var(--ink-2); display:flex; gap:10px; align-items:flex-start; }
.why-body ul li i{ color:var(--accent); margin-top:4px; font-size:10px; }
.why.dark .why-body ul li{ color:rgba(255,255,255,.78); }

/* ─── FAQ accordion (rendered directly from tunnelsai/_faq_data.html on
       every page now -- see docs/SEO_STRATEGY.md Phase 6) ───────────────── */
.sec-faq{ background:var(--bg-2); }
.design-b .accordion,
.sec-faq .accordion{ border:1px solid var(--line); border-radius:16px; overflow:hidden; background:#fff; }
.design-b .accordion-item,
.sec-faq .accordion-item{ border:0 !important; border-bottom:1px solid var(--line) !important; border-radius:0 !important; background:#fff; }
.design-b .accordion-item:last-child,
.sec-faq .accordion-item:last-child{ border-bottom:0 !important; }
.design-b .accordion-button,
.sec-faq .accordion-button{ font-family:'Saira Semi Condensed',sans-serif; font-weight:600; font-size:16px; color:var(--navy) !important; background:#fff !important; box-shadow:none !important; padding:20px 26px; text-transform:uppercase; letter-spacing:0.01em; }
.design-b .accordion-button:not(.collapsed),
.sec-faq .accordion-button:not(.collapsed){ color:var(--navy) !important; background:#fff !important; }
.design-b .accordion-button::after,
.sec-faq .accordion-button::after{ background:none; content:"+"; color:var(--accent); font-family:'IBM Plex Mono',monospace; font-size:20px; transition:transform .2s; width:auto; height:auto; }
.design-b .accordion-button:not(.collapsed)::after,
.sec-faq .accordion-button:not(.collapsed)::after{ transform:rotate(45deg); }
.design-b .accordion-button i{ color:var(--accent); }
.design-b .accordion-body,
.sec-faq .accordion-body{ padding:0 26px 22px; font-size:14px; color:var(--ink-2); line-height:1.6; }
.sec-faq .accordion-body p{ margin-bottom:10px; }
.sec-faq .accordion-body p:last-child{ margin-bottom:0; }

/* ─── Final CTA band ─────────────────────────────────────────────────────── */
.sec-final{ background:var(--navy); color:#fff; position:relative; overflow:hidden; }
.sec-final::before{ content:""; position:absolute; inset:0; background:radial-gradient(circle at 80% 20%,rgba(27,95,168,.22),transparent 50%),radial-gradient(circle at 20% 80%,rgba(21,74,133,.18),transparent 55%); }
.final-h{ font-family:'Saira Semi Condensed',sans-serif; font-weight:700; font-size:64px; line-height:1; color:#fff; text-transform:uppercase; letter-spacing:-0.02em; }
.final-h em{ font-style:normal; color:var(--accent); font-weight:800; }

/* ─── Responsive type defaults (about.html overrides these locally) ─────── */
@media (max-width: 991.98px){
  .display-h1{ font-size:48px; }
  .display-h2{ font-size:38px; }
  .final-h{ font-size:42px; }
  .uc{ padding:24px; }
}

/* ─── Breadcrumbs — tunnelsai/templates/tunnelsai/breadcrumbs.html ───────
   Moved here from blog/static/blog/blog-nav.css (Phase 3, docs/SEO_STRATEGY.md)
   so marketing pages, which don't load that file, can render breadcrumbs
   too (currently /compare/<slug>). Blog keeps getting the rule via
   layout.html — this is a move, not a copy, so there's one source of truth. */
.breadcrumb-nav{ padding:18px 0 0; }
.breadcrumb-nav ol{ display:flex; flex-wrap:wrap; gap:6px; margin:0; padding:0; list-style:none; font-size:13px; color:var(--mute); }
.breadcrumb-nav li{ display:flex; align-items:center; gap:6px; }
.breadcrumb-nav li:not(:last-child)::after{ content:"/"; color:var(--line); margin-left:6px; }
.breadcrumb-nav a{ color:var(--accent); text-decoration:none; }
.breadcrumb-nav a:hover{ text-decoration:underline; }
.breadcrumb-nav [aria-current="page"]{ color:var(--ink-2); }

/* ─── Comparison pages (/compare) — docs/SEO_STRATEGY.md Phase 3 ────────── */
.cmp-legend{ font-size:13px; color:var(--mute); margin-bottom:16px; }
.cmp-matrix-card{ background:#fff; border:1px solid var(--line); border-radius:18px; overflow:hidden; }
.cmp-matrix{ margin-bottom:0; }
.cmp-matrix th, .cmp-matrix td{ padding:16px 18px; font-size:14px; }
.cmp-matrix thead th{ font-family:'Saira Semi Condensed',sans-serif; font-weight:700; text-transform:uppercase; font-size:12px; letter-spacing:0.03em; color:var(--navy); background:var(--bg); border-bottom:1px solid var(--line); }
.cmp-matrix tbody th{ font-weight:600; color:var(--navy); }
.cmp-matrix tbody tr:not(:last-child) th, .cmp-matrix tbody tr:not(:last-child) td{ border-bottom:1px solid var(--line); }
.cmp-source{ display:inline-block; margin-left:6px; font-family:'IBM Plex Mono',monospace; font-size:10.5px; letter-spacing:0.03em; text-transform:uppercase; color:var(--accent); text-decoration:underline; }
.cmp-matrix thead th:nth-child(2){ background:rgba(27,95,168,.06); color:var(--accent); }
.cmp-matrix tbody td:nth-child(2){ background:rgba(27,95,168,.035); }

@media (max-width: 767.98px){
  .cmp-matrix{ min-width:620px; }
  .cmp-matrix thead th:first-child, .cmp-matrix tbody th{ position:sticky; left:0; z-index:1; min-width:170px; }
  .cmp-matrix tbody th{ background:#fff; }
  .cmp-matrix thead th:first-child{ background:var(--bg); }
}

.cmp-pick-card, .cmp-stance{ background:#fff; border:1px solid var(--line); border-radius:18px; padding:28px 30px; height:100%; }
.cmp-pick-card h3{ font-family:'Saira Semi Condensed',sans-serif; font-weight:700; font-size:19px; text-transform:uppercase; color:var(--navy); letter-spacing:-0.005em; margin-bottom:16px; }
.cmp-pick-card ul{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:10px; }
.cmp-pick-card li{ display:flex; align-items:flex-start; gap:10px; font-size:14px; color:var(--ink-2); line-height:1.5; }
.cmp-pick-card li i{ font-size:5px; margin-top:7px; color:var(--accent); flex:0 0 auto; }
.cmp-pick-card--them{ background:var(--bg-2); }

.cmp-verdict{ background:#fff; border:1px solid var(--line); border-left:3px solid var(--accent); border-radius:18px; padding:32px 36px; }
.cmp-verdict-lbl{ font-family:'IBM Plex Mono',monospace; font-size:11px; letter-spacing:0.14em; text-transform:uppercase; color:var(--accent); margin-bottom:12px; }
.cmp-verdict p{ font-size:17px; line-height:1.65; color:var(--ink-2); margin:0; max-width:78ch; }

.cmp-stance{ border-top:3px solid var(--accent); }
.cmp-stance--them{ background:var(--bg-2); border-top-color:var(--line); }
.cmp-stance-lbl{ font-family:'IBM Plex Mono',monospace; font-size:11px; letter-spacing:0.06em; text-transform:uppercase; color:var(--mute); margin-bottom:8px; }
.cmp-stance h3{ font-family:'Saira Semi Condensed',sans-serif; font-weight:700; font-size:24px; text-transform:uppercase; color:var(--navy); letter-spacing:-0.005em; margin-bottom:14px; }
.cmp-stance p{ font-size:15px; line-height:1.6; color:var(--ink-2); margin:0; max-width:60ch; }

@media (max-width: 991.98px){ .cmp-verdict p{ font-size:16px; } }

.cmp-card{ display:flex; flex-direction:column; height:100%; background:#fff; border:1px solid var(--line); border-radius:18px; padding:26px; text-decoration:none; color:inherit; transition:border-color .2s, transform .2s, box-shadow .2s; }
.cmp-card:hover{ border-color:var(--navy); transform:translateY(-2px); box-shadow:0 18px 40px -25px rgba(0,0,0,.15); }
.cmp-card-kicker{ font-family:'IBM Plex Mono',monospace; font-size:11px; letter-spacing:0.06em; text-transform:uppercase; color:var(--mute); margin-bottom:6px; }
.cmp-card h3{ font-family:'Saira Semi Condensed',sans-serif; font-weight:700; font-size:22px; text-transform:uppercase; color:var(--navy); letter-spacing:-0.005em; margin-bottom:10px; }
.cmp-card p{ font-size:14px; color:var(--ink-2); line-height:1.5; flex:1; }
.cmp-card-cta{ font-family:'IBM Plex Mono',monospace; font-size:12px; letter-spacing:0.03em; text-transform:uppercase; color:var(--accent); margin-top:12px; }

/* Sources & method note -- provenance + non-affiliation notice. Docked to the
   bottom of .cmp-matrix-card (_compare_matrix.html) so it reads as a table
   source-note and the "checked" date sits beside the claims it qualifies. The
   base (dashed rule, no fill) is used undocked on compare_index.html. Replaced
   .cmp-disclaimer, a centered <p> orphaned after the final CTA band. */
.cmp-note{ padding-top:18px; border-top:1px dashed var(--line); }
.cmp-note-lbl{ font-family:'IBM Plex Mono',monospace; font-size:10.5px; letter-spacing:0.14em; text-transform:uppercase; color:var(--mute); margin-bottom:8px; }
.cmp-note p{ font-size:12.5px; line-height:1.6; color:var(--ink-2); margin:0; max-width:92ch; }
.cmp-note a{ color:var(--accent); text-decoration:underline; }
.cmp-note--docked{ padding:20px 18px 22px; border-top:1px solid var(--line); background:var(--bg); }

/* ---------- Cookie consent banner (Consent Mode v2) ----------
   tunnelsai/templates/tunnelsai/cookie_banner.html, included site-wide by
   layout.html. z-index 1035: above the footer (95), the glossary sticky
   jumpnav (10), and Bootstrap 5.3's dropdown/sticky/fixed (1000/1020/1030),
   but below its offcanvas-backdrop/modal-backdrop/modal (1040/1050/1055) so
   #registerModal and the pricing modal still render on top of it. Pure
   vanilla CSS -- no Bootstrap JS dependency (see cookie_banner.html's own
   comment). Only tokens declared in BOTH :root blocks (this file and
   layout.html's inline copy) are used here.
   Two breakpoints below: <=768px stacks the layout and tightens spacing so
   the fixed bottom bar doesn't eat a large share of a phone viewport;
   <=575.98px additionally drops the heading line (the region's
   aria-label="Cookie consent" already gives sighted desktop users the same
   context, so it's redundant to spend ~25px of a short viewport on it). */
.cc-bar{
  position:fixed; left:0; right:0; bottom:0; z-index:1035;
  background:var(--bg); color:var(--ink);
  border-top:1px solid var(--line);
  box-shadow:0 -4px 24px rgba(0,0,0,.12);
}
.cc-bar[hidden]{ display:none; }
.cc-inner{
  max-width:1140px; margin:0 auto; padding:18px 24px;
  display:flex; align-items:center; gap:24px; flex-wrap:wrap;
}
.cc-text{ flex:1 1 420px; min-width:260px; font-size:14px; line-height:1.5; color:var(--ink-2); }
.cc-text .cc-heading{ font-weight:600; color:var(--navy); }
.cc-text a{ color:var(--accent); text-decoration:underline; }
.cc-actions{ flex:0 0 auto; display:flex; gap:12px; }
.cc-btn{ border:0; border-radius:8px; padding:10px 20px; font-weight:600; font-size:14px; white-space:nowrap; }
.cc-btn--reject{ background:transparent; color:var(--ink-2); border:1px solid var(--line); }
.cc-btn--reject:hover{ border-color:var(--mute); color:var(--navy); }
.cc-btn--accept{ background:var(--accent); color:#fff; }
.cc-btn--accept:hover{ background:var(--accent-2); }
@media (max-width:768px){
  .cc-inner{ flex-direction:column; align-items:stretch; gap:12px; padding:14px 16px; }
  .cc-text{ flex:1 1 auto; min-width:0; font-size:13px; line-height:1.45; }
  .cc-actions{ justify-content:stretch; gap:10px; }
  .cc-btn{ flex:1 1 0; padding:12px 14px; min-height:44px; }
}
@media (max-width:575.98px){
  .cc-text .cc-heading{ display:none; }
}

/* ─── COST DATA HUB (Phase 4, docs/SEO_STRATEGY.md) ───
   Tables and cards reuse .cmp-matrix/.cmp-matrix-card/.cmp-card/.cmp-note
   from the /compare pages -- this block only covers what's genuinely new:
   the sortable-column affordance and the search input on the hub table. */
#cd-hub-table th[data-sort]{ user-select:none; transition:color .15s ease; }
#cd-hub-table th[data-sort]:hover{ color:var(--accent); }
#cd-hub-table th[data-sort] i{ font-size:10px; margin-left:4px; color:var(--mute); }
#cd-search{ border-radius:10px; border-color:var(--line); }
#cd-search:focus{ border-color:var(--accent); box-shadow:0 0 0 3px rgba(27,95,168,.12); }

/* ─── ESTIMATING TOOLS (docs/ESTIMATING_TOOLS_FRAMEWORK.md) ───
   Purpose-built .est-* calculator-card classes, not restyled Bootstrap
   utilities -- that's what forced the !important pile-up in .sec-calc
   (business-case.html), a mistake this block deliberately avoids. Shared
   by every tool_<slug>.js calculator via _estimating_calc.html; only the
   inline SVG content inside #est-viz differs per tool.
   Surface convention: the card itself is a light grey recess (#f8f9fa,
   Bootstrap's bg-light -- deliberately not the --bg/--bg-2 tokens, and one
   step lighter than the page's own var(--bg) behind it); the diagram
   (.est-calc-viz), quantity table wrap (.est-qty-table-wrap), unit/mode
   toggles and upload dropzone are white panels; the actual input fields
   (.est-field input/select, .est-qty-table .est-cell, the grid-size
   stepper) are explicitly set to white too, since Bootstrap's own white no
   longer applies here -- this file redefines --bs-body-bg to var(--bg) at
   :root, so .form-control/.form-select resolve to the page's grey by
   default. Every such input rule needs a matching :focus rule with its own
   background:#fff, because .form-control:focus re-asserts
   background-color:var(--bs-body-bg) at a specificity that otherwise wins.
   .est-output-tile (the result tiles) deliberately stays var(--bg), not
   white -- it's the one thing in the card that keeps its original colour.
   Don't reintroduce a var(--bg) panel background on the diagram/table/
   toggle/upload wrappers; it disappears against the new card colour. */
.est-calc-card{
  background:#f8f9fa; border:1px solid var(--line); border-radius:18px; padding:26px;
  display:flex; flex-direction:column; gap:22px;
}

/* Diagram (left) / calculation controls (right) columns, shared by every tool via
   _estimating_calc.html. minmax(0, ...) on both tracks keeps a wide child (the
   quantity table) from forcing its track wider than intended instead of using the
   table's own overflow-x:auto. Collapses to one column on mobile, stacking in DOM
   order (diagram above calculation) -- no CSS `order` needed either way. */
.est-calc-columns{ display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1.5fr); gap:24px; align-items:start; }
.est-calc-col-viz, .est-calc-col-inputs{ min-width:0; display:flex; flex-direction:column; gap:22px; }
@media (max-width:991.98px){
  .est-calc-columns{ grid-template-columns:1fr; }
}
/* Cut-and-fill tools only (tool.full_width_viz): full-width diagram on top, full-width
   inputs/table below, at every screen width -- their 1000x380 diagrams (area-weighted
   depth chart / plan-view mesh) read cramped at half the card's width. Two classes
   beats the base rule's specificity, no !important needed. */
.est-calc-columns--stacked{ grid-template-columns:1fr; }
.est-calc-inputs{ display:grid; grid-template-columns:repeat(auto-fit, minmax(160px, 1fr)); gap:14px; }
.est-field{ display:flex; flex-direction:column; }
.est-field label{
  display:block; font-family:'IBM Plex Mono',monospace; font-size:11px; letter-spacing:0.04em;
  text-transform:uppercase; color:var(--mute); margin-bottom:6px;
}
.est-field .est-unit{ color:var(--mute); font-weight:400; text-transform:none; letter-spacing:0; }
/* margin-top:auto pins the control to the bottom of its (grid-stretched) .est-field cell, so every
   input in a .est-shared-inputs row shares a common top/bottom edge regardless of how many lines
   its own label wrapped to -- labels vary in length per tool ("Truck capacity (heaped) (m³)" vs
   "Practical fill factor (%)") and used to leave inputs at different heights in the same row. */
.est-field input, .est-field select{ margin-top:auto; border-radius:8px; border-color:var(--line); background:#fff; }
/* :focus needs its own background:#fff -- Bootstrap's .form-control:focus (specificity 0,2,0)
   re-asserts background-color:var(--bs-body-bg), which this stylesheet redefines to var(--bg)
   at :root -- that out-specifies the (0,1,1) rule above, so without this the field would grey
   out the moment you click into it. */
.est-field input:focus, .est-field select:focus{ border-color:var(--accent); box-shadow:0 0 0 3px rgba(27,95,168,.12); background:#fff; }

.est-calc-viz{ position:relative; background:#fff; border:1px solid var(--line); border-radius:14px; padding:14px; }
.est-calc-viz svg{ width:100%; height:auto; display:block; font-family:'IBM Plex Mono',monospace; }

/* Compact/Expanded layout toggle (round 16, moved onto the graphic from
   .est-toolbar) -- overlaid on .est-calc-viz (its `position:relative` above
   is what anchors this) rather than inside .est-viz3d specifically, so it
   sits over whichever layer -- the SVG fallback or the 3D canvas -- is
   actually visible. z-index above .est-viz3d-labels (below, pointer-events:
   none already) so it stays clickable even if a diagram label happens to
   render underneath it. Same .est-unit-toggle/.est-unit-btn pill as every
   other toggle on the card, just noticeably smaller -- a corner control, not
   a toolbar-weight one. */
.est-viz-layout-toggle{ position:absolute; top:10px; right:10px; z-index:2; }
/* Compound selector (both classes) so this padding override beats
   .est-unit-toggle's own padding:3px below on specificity -- same class
   count, but declared earlier in the file, would otherwise lose the
   cascade on source order alone despite being the more specific intent. */
.est-unit-toggle.est-viz-layout-toggle{ padding:2px; }
.est-viz-layout-toggle .est-unit-btn{ padding:4px 10px; font-size:10.5px; }

/* Any viz3d tool (basic-cut-and-fill, advanced-cut-and-fill, concrete-volume,
   formwork-area, slab-screed-volume): three.js scene, layered over the SVG
   chart above. Hidden until tool_<slug>.js confirms three.js loaded AND a
   WebGL context was obtained -- at that point it adds .est-viz3d--active
   here and .est-viz-hidden-3d on the sibling <svg>, so a visitor with WebGL
   disabled, a failed script load, or JS off entirely always keeps the
   working 2D chart instead of an empty box. Not scoped to a single tool's
   [data-tool] any more -- five tools share this now. */
#est-viz.est-viz-hidden-3d{ display:none; }
.est-viz3d{
  display:none; position:relative; width:100%; aspect-ratio:5/3; border-radius:8px; overflow:hidden;
}
/* Compact (non-expanded) layout only: a little taller than the shared 5/3
   above, so the Compact/Expanded toggle overlaid in the corner (right above)
   has breathing room against the diagram's own labels -- the expanded/
   stacked layout is already wide enough that 5/3 reads comfortably tall. */
.est-calc-columns:not(.est-calc-columns--stacked) .est-viz3d{ aspect-ratio:4/3; }
.est-viz3d.est-viz3d--active{ display:block; }
.est-viz3d canvas{ width:100%; height:100%; display:block; cursor:grab; touch-action:pan-y; }
.est-viz3d canvas:active{ cursor:grabbing; }
.est-viz3d-labels{ position:absolute; inset:0; pointer-events:none; }
.est-viz3d-label{
  position:absolute; left:0; top:0; display:none; white-space:nowrap;
  font-family:'IBM Plex Mono',monospace; font-size:11px; font-weight:600;
  padding:1px 6px; border-radius:4px; background:rgba(255,255,255,.88);
}
.est-viz3d-label--cut{ color:#C0392B; }
.est-viz3d-label--fill{ color:#3E8C5A; }
.est-viz3d-label--datum{ color:#5c6b74; font-weight:500; }
.est-viz3d-label--neutral{ color:#7a766e; font-weight:500; }
/* slab-screed-volume's two layer colours -- same hexes as that tool's own
   drawSvgFallback SVG bands, so the 3D scene and the 2D fallback read as the
   same palette. concrete-volume/formwork-area's per-row labels use --neutral
   above (row identity now comes from color-matching the box/panel/table
   accent below, not from coloring the label text itself -- see the
   per-tool row-accent block further down for why). */
.est-viz3d-label--slab{ color:#5c574c; font-weight:500; }
.est-viz3d-label--screed{ color:#C9793E; font-weight:500; }

.est-calc-outputs{ display:grid; grid-template-columns:repeat(auto-fit, minmax(210px, 1fr)); gap:12px; }
.est-output-tile{ background:var(--bg); border:1px solid var(--line); border-radius:12px; padding:12px 16px; text-align:center; }
.est-output-label{
  font-family:'IBM Plex Mono',monospace; font-size:10.5px; letter-spacing:.10em; text-transform:uppercase;
  color:var(--mute); margin-bottom:4px; line-height:1.3;
}
.est-output-value{ font-family:'Saira Semi Condensed',sans-serif; font-weight:700; font-size:28px; color:var(--navy); line-height:1.1; display:inline; }
.est-output-unit{ font-size:13px; color:var(--mute); margin-top:0; margin-left:6px; display:inline; }

/* Basic cut-and-fill only: color each tile to what it's showing, same red/green pairing
   as the diagram (round 5) -- the other tools' outputs have no built-in cut/fill/net
   meaning, so they stay the plain tile above, just resized. */
#est-calc-card[data-tool="basic-cut-and-fill"] .est-output-tile:nth-child(1){ background:rgba(192,57,43,.08); border-color:rgba(192,57,43,.28); }
#est-calc-card[data-tool="basic-cut-and-fill"] .est-output-tile:nth-child(1) .est-output-value{ color:#C0392B; }
#est-calc-card[data-tool="basic-cut-and-fill"] .est-output-tile:nth-child(2){ background:rgba(62,140,90,.10); border-color:rgba(62,140,90,.30); }
#est-calc-card[data-tool="basic-cut-and-fill"] .est-output-tile:nth-child(2) .est-output-value{ color:#3E8C5A; }
#est-calc-card[data-tool="basic-cut-and-fill"] .est-output-tile:nth-child(3){ background:rgba(62,140,90,.10); border-color:rgba(62,140,90,.30); }
#est-calc-card[data-tool="basic-cut-and-fill"] .est-output-tile:nth-child(3) .est-output-value{ color:#3E8C5A; }
#est-calc-card[data-tool="basic-cut-and-fill"] .est-output-tile:nth-child(3).est-output-tile--negative{ background:rgba(192,57,43,.08); border-color:rgba(192,57,43,.28); }
#est-calc-card[data-tool="basic-cut-and-fill"] .est-output-tile:nth-child(3).est-output-tile--negative .est-output-value{ color:#C0392B; }

/* Net-as-headline layout, basic cut-and-fill only -- the three tiles above are
   equal-weight by default; here Net (the number an estimator actually came
   for) becomes a full-width headline row, with Cut/Fill demoted to a smaller
   supporting row beneath. order:-1 on the netVol tile (3rd in DOM order)
   moves it to that headline row without touching _estimating_calc.html's
   shared, tool-agnostic markup. The direction cue (arrow + trailing label
   text) reuses .est-output-tile--negative, which est-common.js already
   toggles for netVol < 0 -- no JS changes needed. */
#est-calc-card[data-tool="basic-cut-and-fill"] .est-calc-outputs{ grid-template-columns:1fr 1fr; }
@media (max-width:575.98px){
  #est-calc-card[data-tool="basic-cut-and-fill"] .est-calc-outputs{ grid-template-columns:1fr; }
}
#est-calc-card[data-tool="basic-cut-and-fill"] .est-output-tile:nth-child(3){
  grid-column:1 / -1; order:-1; text-align:left; padding:20px 24px;
}
#est-calc-card[data-tool="basic-cut-and-fill"] .est-output-tile:nth-child(3) .est-output-value{ font-size:40px; }
#est-calc-card[data-tool="basic-cut-and-fill"] .est-output-tile:nth-child(3) .est-output-unit{ font-size:15px; }
#est-calc-card[data-tool="basic-cut-and-fill"] .est-output-tile:nth-child(1),
#est-calc-card[data-tool="basic-cut-and-fill"] .est-output-tile:nth-child(2){ padding:10px 14px; }
#est-calc-card[data-tool="basic-cut-and-fill"] .est-output-tile:nth-child(1) .est-output-value,
#est-calc-card[data-tool="basic-cut-and-fill"] .est-output-tile:nth-child(2) .est-output-value{ font-size:20px; }
/* ▲ = net positive = fill > cut = material needed on site; ▼ = net negative =
   cut > fill = surplus to haul away -- matches aggregate()'s sign convention
   in tool_basic-cut-and-fill.js and the existing red/green flip above. */
#est-calc-card[data-tool="basic-cut-and-fill"] .est-output-tile:nth-child(3) .est-output-value::before{ content:"▲ "; }
#est-calc-card[data-tool="basic-cut-and-fill"] .est-output-tile:nth-child(3).est-output-tile--negative .est-output-value::before{ content:"▼ "; }
#est-calc-card[data-tool="basic-cut-and-fill"] .est-output-tile:nth-child(3) .est-output-label::after{ content:" — material to import"; }
#est-calc-card[data-tool="basic-cut-and-fill"] .est-output-tile:nth-child(3).est-output-tile--negative .est-output-label::after{ content:" — surplus to remove"; }

/* Advanced grid tool -- identical tile coloring to the basic tool above, just scoped
   to its own data-tool value. */
#est-calc-card[data-tool="advanced-cut-and-fill"] .est-output-tile:nth-child(1){ background:rgba(192,57,43,.08); border-color:rgba(192,57,43,.28); }
#est-calc-card[data-tool="advanced-cut-and-fill"] .est-output-tile:nth-child(1) .est-output-value{ color:#C0392B; }
#est-calc-card[data-tool="advanced-cut-and-fill"] .est-output-tile:nth-child(2){ background:rgba(62,140,90,.10); border-color:rgba(62,140,90,.30); }
#est-calc-card[data-tool="advanced-cut-and-fill"] .est-output-tile:nth-child(2) .est-output-value{ color:#3E8C5A; }
#est-calc-card[data-tool="advanced-cut-and-fill"] .est-output-tile:nth-child(3){ background:rgba(62,140,90,.10); border-color:rgba(62,140,90,.30); }
#est-calc-card[data-tool="advanced-cut-and-fill"] .est-output-tile:nth-child(3) .est-output-value{ color:#3E8C5A; }
#est-calc-card[data-tool="advanced-cut-and-fill"] .est-output-tile:nth-child(3).est-output-tile--negative{ background:rgba(192,57,43,.08); border-color:rgba(192,57,43,.28); }
#est-calc-card[data-tool="advanced-cut-and-fill"] .est-output-tile:nth-child(3).est-output-tile--negative .est-output-value{ color:#C0392B; }

.est-calc-actions{ display:flex; justify-content:flex-end; gap:12px; }
.est-calc-actions .btn-outline-navy{ font-size:12px; padding:10px 18px; }

/* ─── ESTIMATING TOOLS: grid-input widget (docs/ESTIMATING_TOOLS_FRAMEWORK.md redesign
   plan, round 8) -- generic, not scoped to any one tool's data-tool value, so a future
   grid_input tool can reuse it as-is. The Existing/Proposed layer toggle deliberately
   reuses .est-unit-toggle/.est-unit-btn verbatim (see _estimating_calc_grid.html) rather
   than inventing a second visual pattern for what's functionally the same kind of switch. */
.est-grid-toolbar{ display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:14px; }
.est-grid-size{ display:flex; align-items:center; gap:8px; font-family:'IBM Plex Mono',monospace; font-size:12px; letter-spacing:.03em; color:var(--mute); }
.est-grid-size label{ text-transform:uppercase; letter-spacing:.06em; font-size:10.5px; }
.est-grid-size input[type="number"]{
  width:44px; text-align:center; border:1px solid var(--line); border-radius:6px; padding:5px 2px;
  font-family:'IBM Plex Mono',monospace; font-size:13px; color:var(--navy); background:#fff;
}
.est-grid-size input[type="number"]:focus{ border-color:var(--accent); box-shadow:0 0 0 3px rgba(27,95,168,.12); outline:none; }
.est-grid-size button{
  width:26px; height:26px; border:1px solid var(--line); border-radius:6px; background:#fff;
  color:var(--navy); font-size:14px; line-height:1; cursor:pointer; display:inline-flex; align-items:center; justify-content:center;
}
.est-grid-size button:hover{ background:var(--bg); }

.est-grid-wrap{ overflow-x:auto; }
.est-grid-table{ border-collapse:collapse; margin:0 auto; }
.est-grid-table td{ padding:3px; }
.est-grid-cell{
  width:64px; height:44px; text-align:center; border:1px solid var(--line); border-radius:6px;
  font-family:'IBM Plex Mono',monospace; font-size:13px; color:var(--navy); background:#fff;
}
.est-grid-cell:focus{ border-color:var(--accent); box-shadow:0 0 0 3px rgba(27,95,168,.12); outline:none; }
.est-grid-cell.est-cell-invalid{ border-color:#a6320b; background:rgba(166,50,11,.06); }

/* ─── ESTIMATING TOOLS: units + quantity table + upload
   (docs/ESTIMATING_TOOLS_FRAMEWORK.md §10-11) ───
   Extends the .est-* block above -- same "purpose-built classes, not
   restyled Bootstrap utilities" discipline. */
.est-toolbar{
  display:flex; justify-content:flex-end; align-items:center; gap:14px;
  padding-bottom:16px;
}
.est-unit-toggle{ display:inline-flex; border:1px solid var(--line); border-radius:999px; padding:3px; background:#fff; }
.est-unit-btn{
  border:none; background:none; padding:6px 16px; border-radius:999px; font-size:12px;
  font-family:'IBM Plex Mono',monospace; letter-spacing:.03em; color:var(--mute); cursor:pointer;
}
.est-unit-btn.selected{ background:var(--navy); color:#fff; }

/* Basic/Advanced mode toggle (_estimating_mode_toggle.html) -- reuses .est-unit-toggle/
   .est-unit-btn verbatim (same precedent as the grid tool's Existing/Proposed toggle,
   _estimating_calc_grid.html) so no new pill visual is needed. Sits on the same (right) side as
   the Metric/Imperial toggle via .est-toolbar's own justify-content:flex-end + gap -- no extra
   positioning needed here. Tools with no variant_slug (this partial renders nothing) are
   unaffected either way. */
.est-mode-toggle .selected{ cursor:default; }
/* Loading state for the *other* mode's link -- clicking it is a real page
   navigation (a plain <a href>, see _estimating_mode_toggle.html), not an
   AJAX swap, so this only needs to cover the visible gap while the new
   page's request is in flight (see the inline script in estimating_tool.html
   that swaps the link's content for the spinner and defers navigation by two
   animation frames so the browser actually paints it first). */
.est-mode-toggle a.est-unit-btn.est-mode-toggle-loading{
  pointer-events:none; opacity:.75; display:inline-flex; align-items:center; justify-content:center;
}
.est-mode-toggle .spinner-border{ width:0.8rem; height:0.8rem; border-width:2px; }

.est-shared-inputs{ display:grid; grid-template-columns:repeat(auto-fit, minmax(160px, 1fr)); gap:14px; }

.est-upload{ display:none; border:1px dashed var(--line); border-radius:14px; padding:18px; background:#fff; }
.est-upload.is-open{ display:block; }
.est-dropzone{ cursor:pointer; text-align:center; padding:10px 6px; border-radius:10px; }
.est-dropzone:focus-visible, .est-dropzone--over{ outline:2px solid var(--accent); outline-offset:2px; background:rgba(27,95,168,.06); }
.est-dropzone-headline{ margin-bottom:4px; }
.est-upload-link{ color:var(--accent); text-decoration:underline; cursor:pointer; }
.est-upload-hint, .est-upload-privacy{ font-size:12px; color:var(--mute); margin:2px 0 0; }
.est-upload-actions{ display:flex; flex-wrap:wrap; gap:10px; justify-content:center; margin-top:14px; }
.est-upload-actions .btn-outline-navy{ font-size:12px; padding:8px 14px; }
.est-upload-notice{ margin-top:12px; font-size:12px; color:var(--ink-2); background:#fff; border:1px solid var(--line); border-radius:8px; padding:8px 12px; }
.est-upload-notice--error{ color:#a6320b; border-color:rgba(166,50,11,.35); background:rgba(166,50,11,.06); }

.est-qty-table-wrap{ overflow-x:auto; border:1px solid var(--line); border-radius:14px; background:#fff; }
.est-qty-table{ width:100%; border-collapse:collapse; font-size:13px; }
.est-qty-table thead th{
  font-family:'IBM Plex Mono',monospace; font-size:10.5px; letter-spacing:.03em; text-transform:uppercase;
  color:var(--mute); font-weight:600; text-align:left; padding:10px 10px; background:var(--bg); white-space:nowrap;
  border-bottom:1px solid var(--line);
}
.est-qty-table tbody td{ padding:7px 8px; border-bottom:1px solid var(--line); vertical-align:middle; }
.est-qty-table tbody tr:last-child td{ border-bottom:none; }
.est-qty-table tbody tr:nth-child(even) td{ background:var(--bg); }
.est-qty-table .est-cell{ min-width:88px; border-radius:6px; border-color:var(--line); background:#fff; }
/* :focus needs its own background:#fff for the same reason as .est-field input:focus above --
   .form-control:focus (0,2,0) ties with the base rule here and would otherwise win on source
   order, reverting to var(--bs-body-bg)/var(--bg) while a cell is being edited. */
.est-qty-table .est-cell:focus{ background:#fff; }
.est-qty-table td:first-child .est-cell{ min-width:140px; border-color:transparent; background:transparent; }
.est-qty-table td:first-child .est-cell:hover{ border-color:var(--line); }
.est-qty-table td:first-child .est-cell:focus{ border-color:var(--accent); background:#fff; box-shadow:0 0 0 3px rgba(27,95,168,.12); }
.est-qty-table .est-cell.est-cell-invalid{ border-color:#a6320b; background:rgba(166,50,11,.06); }
.est-qty-table .est-row-output{ font-family:'Saira Semi Condensed',sans-serif; font-weight:600; font-size:17px; color:var(--navy); white-space:nowrap; }
.est-qty-table .est-row-output--zero{ font-weight:400; color:var(--mute); opacity:.6; }

/* Per-row color accent (concrete-volume, formwork-area only) -- a 4px
   left-edge strip on each row's name cell, cycling an 8-hue categorical
   palette by row POSITION (nth-of-type), not by row identity: row 1 always
   gets slot 1 regardless of which named row currently sits there, since
   that's the same index each tool's viz3d IIFE and drawSvgFallback use to
   color that row's own box/panel/SVG bar -- no per-row id tracking needed
   across add/delete, position is already the shared key. Palette is the
   dataviz skill's validated default categorical set (references/palette.md),
   confirmed via its validator against this table's actual white surface --
   not hand-picked. Text itself stays in the existing dark ink tokens (never
   the accent color) per that skill's own rule and because 3 of the 8 hues
   (aqua/yellow/magenta) read below 3:1 on white -- fine for a border strip
   or a solid-lit 3D material, not for text. Base rule reserves the 4px even
   before a row exists, so there's no reflow when JS clones a new row. */
#est-calc-card[data-tool="concrete-volume"] .est-qty-table tbody td:first-child,
#est-calc-card[data-tool="formwork-area"] .est-qty-table tbody td:first-child{
  border-left:4px solid transparent;
}
#est-calc-card[data-tool="concrete-volume"] .est-qty-table tbody tr:nth-of-type(8n+1) td:first-child,
#est-calc-card[data-tool="formwork-area"] .est-qty-table tbody tr:nth-of-type(8n+1) td:first-child{ border-left-color:#2a78d6; }
#est-calc-card[data-tool="concrete-volume"] .est-qty-table tbody tr:nth-of-type(8n+2) td:first-child,
#est-calc-card[data-tool="formwork-area"] .est-qty-table tbody tr:nth-of-type(8n+2) td:first-child{ border-left-color:#eb6834; }
#est-calc-card[data-tool="concrete-volume"] .est-qty-table tbody tr:nth-of-type(8n+3) td:first-child,
#est-calc-card[data-tool="formwork-area"] .est-qty-table tbody tr:nth-of-type(8n+3) td:first-child{ border-left-color:#1baf7a; }
#est-calc-card[data-tool="concrete-volume"] .est-qty-table tbody tr:nth-of-type(8n+4) td:first-child,
#est-calc-card[data-tool="formwork-area"] .est-qty-table tbody tr:nth-of-type(8n+4) td:first-child{ border-left-color:#eda100; }
#est-calc-card[data-tool="concrete-volume"] .est-qty-table tbody tr:nth-of-type(8n+5) td:first-child,
#est-calc-card[data-tool="formwork-area"] .est-qty-table tbody tr:nth-of-type(8n+5) td:first-child{ border-left-color:#e87ba4; }
#est-calc-card[data-tool="concrete-volume"] .est-qty-table tbody tr:nth-of-type(8n+6) td:first-child,
#est-calc-card[data-tool="formwork-area"] .est-qty-table tbody tr:nth-of-type(8n+6) td:first-child{ border-left-color:#008300; }
#est-calc-card[data-tool="concrete-volume"] .est-qty-table tbody tr:nth-of-type(8n+7) td:first-child,
#est-calc-card[data-tool="formwork-area"] .est-qty-table tbody tr:nth-of-type(8n+7) td:first-child{ border-left-color:#4a3aa7; }
#est-calc-card[data-tool="concrete-volume"] .est-qty-table tbody tr:nth-of-type(8n) td:first-child,
#est-calc-card[data-tool="formwork-area"] .est-qty-table tbody tr:nth-of-type(8n) td:first-child{ border-left-color:#e34948; }

/* Combined signed Cut/Fill table cell (round 14) -- basic cut-and-fill tool
   only, scoped via the existing #est-calc-card[data-tool] attribute so the
   other tools are unaffected. Replaces the old separate [data-out="cut"]/
   [data-out="fill"] pair (one of which was always zero) with a single
   [data-out="net"] column: green by default (fill/positive), red via the
   generic .est-row-output--negative sign hook (est-common.js, cut/negative),
   gray via the existing --zero hook (neither). The "+" prefix is added only
   on the positive/non-zero case -- fmtDim's Intl.NumberFormat already
   renders a negative value's own "-", so the negative case needs no prefix.
   display:inline-block/a tighter padding used to be set here directly on the
   <td> itself (.est-row-output IS the <td>, see _estimating_calc.html) --
   that breaks a table cell's default vertical-align:middle and shrinks it
   below its row's height, which is why these cells looked top-left-aligned
   and shorter than the input cells next to them. Dropping both lets the cell
   stay a normal table-cell, inheriting .est-qty-table tbody td's own
   vertical-align:middle and padding:7px 8px so every cell in the row matches.
   --zero also gets a bare [data-out] added so its specificity matches
   [data-out="net"] exactly -- without it, a zeroed cell matched both rules
   and the colored one (declared first here, but higher specificity due to
   its extra attribute selector) always won, so a zero value stayed green
   (just faded by --zero's opacity) instead of the plain gray --zero intends.
   (advanced-cut-and-fill never had an equivalent block worth keeping here --
   its grid shell renders no .est-row-output cells at all.) */
#est-calc-card[data-tool="basic-cut-and-fill"] .est-row-output[data-out="net"]{
  background:rgba(62,140,90,.12); color:#3E8C5A; border-radius:6px;
}
#est-calc-card[data-tool="basic-cut-and-fill"] .est-row-output[data-out="net"]:not(.est-row-output--zero)::before{
  content:"+";
}
#est-calc-card[data-tool="basic-cut-and-fill"] .est-row-output--negative[data-out="net"]{
  background:rgba(192,57,43,.12); color:#C0392B;
}
/* :not(.est-row-output--zero) repeated here (redundant in practice -- a
   negative value is never also zero) purely to match the "+" rule above's
   specificity ((0,3,1) each): without it this selector is only (0,2,1) and
   the "+" rule -- despite being the "default" case -- would win the cascade
   on specificity alone regardless of source order, incorrectly prefixing
   a "+" onto negative (cut) values too. */
#est-calc-card[data-tool="basic-cut-and-fill"] .est-row-output--negative[data-out="net"]:not(.est-row-output--zero)::before{
  content:none;
}
#est-calc-card[data-tool="basic-cut-and-fill"] .est-row-output--zero[data-out]{
  background:transparent; color:var(--mute); font-weight:400; opacity:.55;
}
.est-row-actions-col{ width:36px; text-align:center; }
.est-row-delete{
  border:none; background:none; color:var(--mute); font-size:18px; line-height:1; cursor:pointer; padding:2px 8px;
  border-radius:6px;
}
.est-row-delete:hover{ color:#a6320b; background:rgba(166,50,11,.08); }
.est-qty-row--invalid{ background:rgba(166,50,11,.04); }

.est-qty-table-actions{ display:flex; justify-content:flex-start; }
.est-qty-table-actions .btn-outline-navy{ font-size:12px; padding:8px 16px; }

/* Output-tile summary, sits right under the toolbar above the diagram/table. Not sticky --
   scrolls away normally with the rest of the card. No background of its own -- it's a full-bleed
   strip (margin:0 -26px) over the card, so an opaque fill here would paint a band across the card's
   own colour; the .est-output-tile children keep their own var(--bg) background regardless. */
.est-sticky-summary{
  padding:14px 0;
  margin:0 -26px; padding-left:26px; padding-right:26px;
}

/* Cut/fill diagram legend + caption -- hidden on every tool (round 15).
   basic-cut-and-fill dropped its title+legend first (round 11) as redundant
   with the diagram's own "Existing ground"/"Proposed level" labels and the
   result tiles above; advanced-cut-and-fill kept its own "Grid mesh (3D
   terrain)" title + Cut/Fill swatch legend for several rounds as a
   deliberate asymmetry, until the user asked for it to be dropped too
   (round 15) -- there is no longer a tool that shows this. The
   {% if tool.has_row_kind %} template guard keeps the (now permanently
   hidden) markup out of neither tool's DOM meaningfully -- it just never
   displays. `Tool.viz_title`/`viz_note` stay declared on both tools' dataclass
   entries regardless (inert once hidden, same as basic's already were). */
.est-viz-legend{
  display:none; align-items:baseline; gap:14px; flex-wrap:wrap; margin-bottom:10px;
  font-family:'IBM Plex Mono',monospace; font-size:10.5px; letter-spacing:.10em; text-transform:uppercase; color:var(--mute);
}
.est-viz-legend-swatches{ margin-left:auto; display:flex; gap:14px; font-size:11.5px; text-transform:none; letter-spacing:0; }
.est-viz-legend-swatch{ display:inline-flex; align-items:center; gap:6px; }
.est-viz-legend-dot{ width:12px; height:12px; border-radius:2px; display:inline-block; }
.est-viz-legend-dot--cut{ background:rgba(192,57,43,.30); border:1px solid #C0392B; }
.est-viz-legend-dot--fill{ background:rgba(62,140,90,.22); border:1px dashed #3E8C5A; }
.est-viz-note{ font-size:12px; color:var(--mute); margin:12px 0 0; line-height:1.5; }
/* Dynamic below-the-graphic caption (concrete-volume's "Depth exaggerated" note today) --
   present on every viz3d tool's markup but starts empty; collapses to nothing rather than
   leaving a stray blank-line gap on tools that never write into it. */
.est-viz-note--dynamic:empty{ display:none; margin:0; }

/* ─── Estimating-tool page shell: dark hero, theory/FAQ card + sidebar ───
   (docs/ESTIMATING_TOOLS_FRAMEWORK.md redesign plan). Reuses
   .feature-hero--dark's existing full-bleed ::before + isolation:isolate
   technique verbatim (see CLAUDE.md "Feature-page Hero Backgrounds") --
   .est-hero only adds the grid texture and layout on top of it. */
/* py-5 deliberately NOT used on this section -- Bootstrap's utility classes are
   !important (confirmed: .py-5{padding-top:3rem!important;padding-bottom:3rem!important}),
   which silently defeated an earlier padding-bottom override here and let the
   calculator card (negative-margin-overlapped below) intrude into the hero's own
   button/pills. .est-hero now owns its vertical spacing outright. margin-top is the
   breadcrumb breathing-room gap -- margin, not padding, so it sits outside the box
   the full-bleed ::before pseudo covers and doesn't affect that technique. */
.est-hero{ isolation:isolate; padding-top:48px; padding-bottom:96px; }
.est-hero::after{
  content:""; position:absolute; inset:0; pointer-events:none; z-index:0;
  background-image:
    linear-gradient(rgba(255,255,255,.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.05) 1px, transparent 1px);
  background-size:44px 44px;
  -webkit-mask-image:radial-gradient(820px 440px at 22% 8%, #000, transparent 85%);
  mask-image:radial-gradient(820px 440px at 22% 8%, #000, transparent 85%);
}
.est-hero-top{ position:relative; z-index:1; display:flex; align-items:flex-end; justify-content:space-between; gap:32px; flex-wrap:wrap; }
.est-hero-content{ width:100%; }
.est-hero-content .lede{ max-width:none; }
.est-hero-badge{
  width:44px; height:44px; border-radius:12px; background:rgba(27,95,168,.22);
  border:1px solid rgba(110,160,215,.34); display:inline-flex; align-items:center; justify-content:center; flex:0 0 auto;
}
/* Every tabler-*.svg icon (tunnelsai/static/tunnelsai/images/lightmode_icons/estimating/) is a
   uniform fill:none / stroke:#1a1a1a graphic rendered via a plain <img>, so CSS can't reach its
   stroke directly -- brightness(0) invert(1) is the standard forced-white recolor for a single-
   color <img>-embedded SVG. Scoped to this badge only: the same icon files are also used by
   estimating_hub.html's .dt-tile-icon on a light tile background, which must stay dark. */
.est-hero-badge img{ width:26px; height:26px; filter: brightness(0) invert(1); }
.est-hero-breadcrumb{
  font-family:'IBM Plex Mono',monospace; font-size:11px; letter-spacing:.06em; text-transform:uppercase;
  display:flex; align-items:center; gap:8px; flex-wrap:wrap; color:rgba(255,255,255,.5);
}
.est-hero-breadcrumb a{ color:rgba(255,255,255,.65); }
.est-hero-breadcrumb a:hover{ color:#fff; text-decoration:underline; }
.est-hero-breadcrumb .current{ color:#8fb6e2; }
.est-hero-breadcrumb .sep{ opacity:.4; }

.est-calc-wrap{ position:relative; z-index:5; margin-top:-64px; }

/* Wraps the Method & theory / Related tools section below the calculator --
   was Bootstrap's plain py-5 (48px top and bottom); the calculator->theory
   gap needed more air than that, so this owns the section's full vertical
   padding instead of adding a competing padding-top utility (Bootstrap's
   utilities are !important -- see the Feature-page Hero Backgrounds note in
   CLAUDE.md for the bug this exact pattern caused once already). Bottom
   padding is unchanged from py-5. */
.est-theory-section{ padding-top:96px; padding-bottom:48px; }

.est-theory-card{ background:#fff; border:1px solid var(--line); border-radius:16px; padding:40px; }
.est-card-eyebrow{ font-family:'IBM Plex Mono',monospace; font-size:11px; letter-spacing:.14em; text-transform:uppercase; color:var(--accent); }

.est-sidebar{ display:flex; flex-direction:column; gap:20px; }
.est-sidebar-card{ background:#fff; border:1px solid var(--line); border-radius:16px; padding:26px; }
.est-related-list{ margin-top:8px; }
.est-related-list a{
  display:flex; align-items:center; justify-content:space-between; gap:12px; padding:13px 10px;
  border-radius:9px; font-size:15px; font-weight:600; color:var(--navy);
}
.est-related-list a:hover{ background:var(--bg); color:var(--accent); }
.est-related-list a i{ font-size:12px; color:var(--mute); }

.est-bridge-card{ background:var(--navy); border:1px solid var(--navy); border-radius:16px; padding:30px; color:#fff; }
.est-bridge-card h3{ font-family:'Saira Semi Condensed',sans-serif; font-weight:700; font-size:24px; text-transform:uppercase; color:#fff; margin:12px 0 14px; }
.est-bridge-card p{ font-size:14.5px; color:rgba(255,255,255,.72); line-height:1.6; }
.est-bridge-card em{ font-style:normal; color:#8fb6e2; }
.est-bridge-card .btn-accent{ margin-top:4px; }

@media (max-width:991.98px){
  .est-calc-wrap{ margin-top:24px; padding-left:0; padding-right:0; }
  .est-hero{ padding-bottom:40px; }
  .est-theory-section{ padding-top:56px; }
}
