/* Self-hosted Google Fonts */
@font-face {
  font-family: 'Lora';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/lora-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Lora';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/lora-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Lora';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/lora-700-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Lora';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/lora-700-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/montserrat-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/montserrat-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/montserrat-600-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/montserrat-600-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

h1, h2, h3, h4 {
    font-family: 'Montserrat', sans-serif;
    font-weight: 600;
}

body, p {
    font-family: 'Lora', serif;
    font-weight: 400; 
    line-height: 1.6; 
}

a, .button, .btn {
    font-family: 'Montserrat', sans-serif;
    font-weight: 600; 
}

h1 {
    font-size: 2.5rem;
}

p {
    font-size: 1.125rem; 
    line-height: 1.75;  
}

.custom-linkedin-badge a {
    color: rgba(220, 38, 38, 1); 
    border-color: rgba(220, 38, 38, 1); 
    font-size: 1rem;
    padding: 0.5rem 1.5rem;
    border-radius: 8px;
    transition: background-color 0.3s ease, color 0.3s ease;
}

.custom-linkedin-badge a:hover {
    background-color: rgba(220, 38, 38, 1);
    color: #fff; 
}   

.service-link {
    font-family: inherit;
    color: inherit;
    cursor: pointer;
}

html {
    scroll-behavior: smooth;
}

.scroll-indicator {
    display: flex;
    flex-direction: column;
    align-items: center;
    cursor: pointer;
    gap: 2px;
    padding: 12px;
    min-height: 44px;
    min-width: 44px;
    justify-content: center;
    -webkit-tap-highlight-color: transparent;
    opacity: 1;
    transition: opacity 0.4s ease-out;
}

.scroll-indicator.scroll-indicator-hidden {
    opacity: 0;
    pointer-events: none;
}

.scroll-chevron {
    animation: scrollDown 2s ease-in-out infinite;
    opacity: 0.6;
    transition: opacity 0.3s ease;
}

.scroll-chevron-delayed {
    animation-delay: 0.25s;
    opacity: 0.5;
}

.scroll-indicator:hover .scroll-chevron,
.scroll-indicator:active .scroll-chevron {
    opacity: 1;
}

.scroll-indicator:hover .scroll-chevron-delayed,
.scroll-indicator:active .scroll-chevron-delayed {
    opacity: 0.8;
}

@keyframes scrollDown {
    0% {
        transform: translateY(0);
        opacity: 0.6;
    }
    50% {
        transform: translateY(10px);
        opacity: 0.4;
    }
    100% {
        transform: translateY(0);
        opacity: 0.6;
    }
}

@media (max-width: 768px) {
    .scroll-indicator {
        padding: 10px;
    }
    
    .scroll-chevron {
        animation: scrollDownMobile 2s ease-in-out infinite;
    }
    
    .scroll-chevron-delayed {
        animation: scrollDownMobile 2s ease-in-out infinite;
        animation-delay: 0.25s;
    }
}

@keyframes scrollDownMobile {
    0% {
        transform: translateY(0);
        opacity: 0.6;
    }
    50% {
        transform: translateY(8px);
        opacity: 0.4;
    }
    100% {
        transform: translateY(0);
        opacity: 0.6;
    }
}

/* Testimonials Carousel */
.testimonials-carousel {
    position: relative;
    overflow: hidden;
    padding: 5px 60px;
}

.testimonials-track {
    display: flex;
    align-items: stretch;
    transition: transform 0.5s ease-in-out;
}

.testimonial-slide {
    min-width: 100%;
    opacity: 0;
    transition: opacity 0.5s ease-in-out;
    display: flex;
}

.testimonial-slide > div {
    width: 100%;
    display: flex;
    flex-direction: column;
}

.testimonial-slide.active {
    opacity: 1;
}

.carousel-button {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    background-color: rgba(255, 255, 255, 0.9);
    border: 2px solid rgba(220, 38, 38, 0.3);
    border-radius: 50%;
    width: 48px;
    height: 48px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all 0.3s ease;
    z-index: 10;
    -webkit-tap-highlight-color: transparent;
}

.carousel-button:hover {
    background-color: rgba(220, 38, 38, 1);
    border-color: rgba(220, 38, 38, 1);
}

.carousel-button:hover svg {
    stroke: white;
}

.carousel-button:active {
    transform: translateY(-50%) scale(0.95);
}

.carousel-button.prev {
    left: 0;
}

.carousel-button.next {
    right: 0;
}

.carousel-button svg {
    width: 24px;
    height: 24px;
    stroke: rgba(220, 38, 38, 1);
    transition: stroke 0.3s ease;
}

.carousel-dots {
    display: flex;
    justify-content: center;
    gap: 12px;
    margin-top: 24px;
}

.carousel-dot {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background-color: rgba(156, 163, 175, 0.5);
    cursor: pointer;
    transition: all 0.3s ease;
    border: 2px solid transparent;
}

.carousel-dot:hover {
    background-color: rgba(220, 38, 38, 0.5);
}

.carousel-dot.active {
    background-color: rgba(220, 38, 38, 1);
    transform: scale(1.2);
}

@media (max-width: 1024px) {
    /* Mobile/tablet: stack vertically — track on top, then [prev] [dots] [next] in a row */
    .testimonials-carousel {
        display: grid;
        grid-template-columns: auto 1fr auto;
        grid-template-areas:
            "track track track"
            "prev  dots  next";
        column-gap: 12px;
        row-gap: 16px;
        padding: 5px 4px;
    }

    .testimonials-track {
        grid-area: track;
    }

    .carousel-button {
        position: static;
        transform: none;
        width: 36px;
        height: 36px;
    }

    .carousel-button.prev {
        grid-area: prev;
    }

    .carousel-button.next {
        grid-area: next;
    }

    .carousel-button:active {
        transform: scale(0.95);
    }

    .carousel-button svg {
        width: 18px;
        height: 18px;
    }

    .carousel-dots {
        grid-area: dots;
        margin-top: 0;
        align-self: center;
        gap: 10px;
    }

    .carousel-dot {
        width: 10px;
        height: 10px;
    }
}

/* Services Tabs */
.services-tablist {
    display: flex;
    flex-wrap: wrap;
    padding-bottom: 0.25rem;
    gap: 3rem;
    justify-content: flex-start;
    margin-bottom: 0.5rem;
    margin-top: 3rem;
}

.services-tab {
    font-family: 'Montserrat', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    font-weight: 600;
    font-size: 1.2rem;
    color: #6B7280;
    background: none;
    border: none;
    padding: 0 0 0.65rem;
    border-bottom: 2px solid transparent;
    cursor: pointer;
    transition: color 0.2s ease, border-color 0.2s ease;
}

.services-tab:hover {
    color: #b91c1c;
}

.services-tab:focus-visible {
    outline: none;
    border-color: rgba(220, 38, 38, 0.35);
}

.services-tab.active {
    color: #111827;
    border-color: #DC2626;
}

.tab-panel {
    display: none;
    animation: fadeIn 0.25s ease-in;
    background-color: #FFFFFF;
    padding: 1rem;
    margin-top: 0.5rem;
}

.tab-panel.active {
    display: block;
}

@keyframes fadeIn {
    from {
        opacity: 0;
        transform: translateY(6px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@media (max-width: 640px) {
    .services-tablist {
        justify-content: center;
        gap: 1.25rem;
    }

    .services-tab {
        padding-bottom: 0.45rem;
        font-size: 1.2rem;
    }

    /* Drop wrapper padding on mobile so cards reach the container edges, matching the Why Hire grid */
    .tab-panel {
        padding: 0;
        background-color: transparent;
    }
}

.services-section h2 {
    margin-bottom: 2.25rem;
}

/* Blog Styles */
.blog-card {
    display: block;
    background: #fff;
    border-radius: 12px;
    overflow: hidden;
    transition: transform 0.3s ease, box-shadow 0.3s ease;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
    border: 1px solid rgba(0, 0, 0, 0.06);
}

.blog-card:hover {
    transform: translateY(-4px);
    box-shadow: 0 12px 24px rgba(0, 0, 0, 0.1);
}

.blog-card-image {
    aspect-ratio: 16 / 9;
    background: linear-gradient(135deg, #f3f4f6 0%, #e5e7eb 100%);
    position: relative;
    overflow: hidden;
}

.blog-card-image::before {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(135deg, rgba(220, 38, 38, 0.05) 0%, rgba(220, 38, 38, 0.1) 100%);
}

.blog-card-content {
    padding: 1.5rem;
}

.blog-featured {
    grid-column: 1 / -1;
}

.blog-featured .blog-card-image {
    aspect-ratio: 21 / 9;
}

.blog-featured .blog-card-content {
    padding: 2rem;
}

.category-badge {
    display: inline-block;
    font-family: 'Montserrat', sans-serif;
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    padding: 0.25rem 0.75rem;
    border-radius: 9999px;
}

.category-engineering {
    background-color: rgba(220, 38, 38, 0.1);
    color: #dc2626;
}

.category-teams {
    background-color: rgba(37, 99, 235, 0.1);
    color: #2563eb;
}

.category-strategy {
    background-color: rgba(22, 163, 74, 0.1);
    color: #16a34a;
}

.category-research {
    background-color: rgba(124, 58, 237, 0.1);
    color: #7c3aed;
}

.article-meta {
    display: flex;
    align-items: center;
    gap: 1rem;
    font-family: 'Montserrat', sans-serif;
    font-size: 0.875rem;
    color: #6b7280;
}

.article-meta svg {
    width: 16px;
    height: 16px;
    opacity: 0.6;
}

.article-meta-item {
    display: flex;
    align-items: center;
    gap: 0.35rem;
}

.reading-progress {
    position: fixed;
    top: 0;
    left: 0;
    width: 0%;
    height: 3px;
    background: linear-gradient(90deg, #dc2626 0%, #ef4444 100%);
    z-index: 9999;
    transition: width 0.1s ease-out;
}

.author-section {
    display: flex;
    align-items: flex-start;
    gap: 1.5rem;
    padding: 2rem;
    /* Deliberately unfilled: the article foot already stacks a form, the
       related cards and a CTA. Four grey boxes in a row read as clutter, so
       this one is separated by a rule instead. */
    border-top: 1px solid #e5e7eb;
    padding-left: 0;
    padding-right: 0;
    margin-top: 3rem;
}

.author-avatar {
    width: 80px;
    height: 80px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
}

.author-info h4 {
    font-size: 1.125rem;
    margin-bottom: 0.25rem;
}

.author-info .author-title {
    font-family: 'Montserrat', sans-serif;
    font-size: 0.875rem;
    color: #6b7280;
    margin-bottom: 0.75rem;
}

.author-info .author-bio {
    font-size: 1rem;
    color: #4b5563;
    margin-bottom: 1rem;
    line-height: 1.6;
}

.author-link {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-family: 'Montserrat', sans-serif;
    font-size: 0.875rem;
    font-weight: 600;
    color: #dc2626;
    transition: opacity 0.2s ease;
}

.author-link:hover {
    opacity: 0.8;
}

.related-articles {
    margin-top: 4rem;
    padding-top: 3rem;
    border-top: 1px solid #e5e7eb;
}

.related-articles h2 {
    font-size: 1.5rem;
    margin-bottom: 1.5rem;
}

.related-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 1.5rem;
}

.related-card {
    display: block;
    padding: 1.25rem;
    background: #f9fafb;
    /* The border carries the separation: a grey card on a white page vanishes
       into it without one, the same rule the related-links blocks follow. */
    border: 1px solid #e5e7eb;
    border-radius: 8px;
    transition: background-color 0.2s ease, transform 0.2s ease;
}

.related-card:hover {
    background: #f3f4f6;
    transform: translateY(-2px);
}

.related-card h4 {
    font-size: 1.125rem;
    margin-bottom: 0.5rem;
    line-height: 1.4;
}

.related-card p {
    font-size: 0.9rem;
    color: #6b7280;
    line-height: 1.5;
}

@media (max-width: 768px) {
    main.container {
        padding-left: 2rem;
        padding-right: 2rem;
    }

    .author-section {
        flex-direction: column;
        align-items: center;
        text-align: center;
    }

    .blog-featured .blog-card-image {
        aspect-ratio: 16 / 9;
    }

    .blog-featured .blog-card-content {
        padding: 1.5rem;
    }
}
/* ============================================================
   Editorial layout system (homepage)
   One column width, two primitives: .ed-row and .ed-col.
   Everything else is spacing and rules. No shadows, no radii.
   ============================================================ */

/* Longhand on purpose: the shorthand forms would reset margin-top and
   padding-top, silently killing any vertical spacing utility set on the
   same element. */
.ed-wrap {
    /* Explicit, and load-bearing: .ed-hero is a flex column at >=768px, so a
       .ed-wrap inside it is a flex item — and a flex item with width:auto is
       sized SHRINK-TO-FIT, not stretched. Left implicit, the column collapses
       to its widest child and its own auto margins then re-centre it, so the
       hero drifts inward and stops sharing the page's left edge.

       Today that is masked: the hero lede is uncapped and happens to be wide
       enough to hold the column open to its 64rem max. That makes this a
       latent bug, not a dormant one — anything that narrows the hero's widest
       child (a measure on the lede, a shorter headline, text-wrap: balance)
       collapses the column on every hero page at once, and no static check can
       see it. The column's width must not depend on what is inside it. */
    width: 100%;
    max-width: 64rem;
    margin-left: auto;
    margin-right: auto;
    padding-left: 1.5rem;
    padding-right: 1.5rem;
}

@media (min-width: 768px) {
    .ed-wrap {
        padding-left: 2rem;
        padding-right: 2rem;
    }
}

.ed-section {
    width: 100%;
    padding: 4rem 0;
}

/* Sections alternate white / gray. The band does the separating, which is
   why no section carries a rule. */
.ed-section--alt {
    background-color: #f9fafb;
}

.ed-section--alt a.ed-row:hover,
.ed-section--alt .ed-art:hover {
    background-color: #fff;
}

@media (min-width: 768px) {
    .ed-section {
        padding: 5.5rem 0;
    }
}

/* Dark accent band. It exists as a system variant because the obvious approach
   — Tailwind's bg-gray-900 on an .ed-section--alt — silently loses: both are
   single-class selectors and styles.css loads last, so --alt's #f9fafb won and
   the section rendered white text on near-white. The eyebrow lightens to red-400
   because red-600 only manages ~4:1 against this background. */
.ed-section--dark {
    background-color: #111827;
    color: #fff;
}

.ed-section--dark h2,
.ed-section--dark h3 { color: #fff; }

.ed-section--dark .ed-eyebrow { color: #f87171; }

.ed-section--dark .ed-lede,
.ed-section--dark p { color: #d1d5db; }

.ed-eyebrow {
    font-family: 'Montserrat', sans-serif;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: #dc2626;
    margin: 0 0 0.9rem;
}

.ed-section h2 {
    font-size: 1.875rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1.2;
    margin: 0 0 1rem;
}

.ed-lede {
    font-size: 1.125rem;
    color: #4b5563;
    line-height: 1.7;
    margin: 0 0 3.25rem;
}

/* --- primitive: ruled row --- */
/* Lists are fenceless: separators sit *between* items only. */
.ed-rows > * + * {
    border-top: 1px solid #e5e7eb;
}

.ed-row {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.5rem;
    padding: 2.5rem 1rem;
    margin: 0 -1rem;
    text-decoration: none;
    color: inherit;
    transition: background-color 0.18s ease;
}

@media (min-width: 768px) {
    .ed-row {
        grid-template-columns: repeat(12, 1fr);
        gap: 3rem;
        align-items: baseline;
    }

    .ed-row .ed-k { grid-column: span 4; }
    .ed-row .ed-v { grid-column: span 7; }
    .ed-row .ed-go { grid-column: span 1; justify-self: end; }
}

a.ed-row:hover { background-color: #fafafa; }
a.ed-row:hover .ed-k h3 { color: #dc2626; }

.ed-row h3 {
    font-size: 1.1875rem;
    font-weight: 600;
    margin: 0;
    transition: color 0.18s ease;
}

.ed-row .ed-v p { margin: 0; color: #4b5563; }

.ed-row .ed-go {
    display: none;
    font-family: 'Montserrat', sans-serif;
    font-size: 1.25rem;
    color: #d1d5db;
    transition: transform 0.18s ease, color 0.18s ease;
}

@media (min-width: 768px) {
    .ed-row .ed-go { display: block; }
}

a.ed-row:hover .ed-go {
    color: #dc2626;
    transform: translateX(4px);
}

.ed-row--accent {
    border-left: 2px solid #dc2626;
    padding-left: 1.5rem;
    margin-left: -1.5rem;
}

.ed-price {
    font-family: 'Montserrat', sans-serif;
    font-size: 1.75rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    margin: 0.25rem 0 0;
}

.ed-price small {
    font-size: 0.9375rem;
    font-weight: 400;
    color: #6b7280;
}

.ed-meta {
    font-size: 0.8125rem;
    color: #6b7280;
    margin: 0.15rem 0 0;
}

.ed-feat {
    margin: 1.25rem 0 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: 0.45rem 0.5rem;
    font-size: 0.9375rem;
    color: #4b5563;
}

.ed-feat li {
    padding-left: 1.4rem;
    text-indent: -1.4rem;
}

@media (min-width: 640px) {
    .ed-feat {
        grid-template-columns: 1fr 1fr;
        column-gap: 2rem;
    }
}

.ed-feat li::before {
    content: "—";
    color: #dc2626;
    margin-right: 0.5rem;
}

.ed-link {
    color: #dc2626;
    font-family: 'Montserrat', sans-serif;
    font-size: 0.875rem;
    font-weight: 600;
    text-decoration: none;
    display: inline-block;
    margin-top: 0.9rem;
}

.ed-link:hover { text-decoration: underline; }

/* --- primitive: ruled column --- */
.ed-cols {
    display: grid;
    gap: 3rem;
}

@media (min-width: 768px) {
    .ed-cols--3 { grid-template-columns: repeat(3, 1fr); }
    .ed-cols--2 { grid-template-columns: repeat(2, 1fr); }
}

.ed-col {
    display: block;
    border-top: 1px solid #111827;
    padding-top: 1.5rem;
    text-decoration: none;
    color: inherit;
    transition: border-color 0.18s ease;
}

a.ed-col:hover { border-color: #dc2626; }

/* The soft red field behind a hero's card stack.

   These heroes put white cards on white, so they need some ground or the
   cards float on nothing — but tinting the whole hero is not an option: the
   sticky header is white and borderless at rest, so a tinted hero draws a
   visible seam right under the bar. This tints only the area behind the cards,
   leaving the top of the hero white where the header meets it.

   A rounded RECT, not the circle it used to be. `rounded-full` stretched over a
   tall two-card stack renders as an ellipse, so what actually showed were two
   pink smudges at opposite corners rather than a field; the rect follows the
   shape of the thing it sits behind. Opacity is .4 rather than the old .2,
   which at 40px of blur was barely distinguishable from white. */
.ed-hero-halo {
    position: absolute;
    inset: -1.75rem;
    background-color: #fee2e2;
    border-radius: 1.75rem;
    opacity: 0.4;
    filter: blur(44px);
    pointer-events: none;
}

/* Comparison tables. The ten on the site were built from fills — a grey
   thead (gray-200 on seven pages, gray-100 on the other three), a white
   tbody, zebra rows — stacked on a grey --alt band, so three greys competed
   and nothing was ruled. This is the same table in the system's vocabulary:
   hairlines, no fills, and the accent spent once on the column heading rather
   than on every cell in it.

   table-layout:fixed matters. Left to auto, the columns sized to their content
   (311/267/382 on the hire page), so the two things being compared got
   different widths and the comparison read as weighted before you'd read a
   word. */
.ed-table {
    width: 100%;
    border-collapse: collapse;
    table-layout: fixed;
    font-family: 'Montserrat', sans-serif;
}

.ed-table th,
.ed-table td {
    text-align: left;
    font-size: 1rem;
    padding: 0.9rem 1rem 0.9rem 0;
    border-bottom: 1px solid #e5e7eb;
}

.ed-table thead th {
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: #6b7280;
    padding-bottom: 0.7rem;
    border-bottom: 1px solid #111827;
}

/* The column this site is arguing for. */
.ed-table thead th:nth-child(2) { color: #dc2626; }

/* Column 1 labels the row; column 2 is always this site's own option; every
   column after that is something it is being compared against. Written as
   nth-child(n+3), not nth-child(3), because these tables are not all the same
   shape — six compare two things, three compare three, and the Spanish
   "what is a fractional CTO" page compares four (Fraccional / Consultor /
   Interino / Asesor). Naming only column 3 left the later comparators dark and
   reading as though they were also ours. */
.ed-table td:first-child { font-weight: 500; color: #111827; }
.ed-table td:nth-child(2) { font-weight: 600; color: #111827; }
.ed-table td:nth-child(n+3) { color: #6b7280; }

.ed-table tbody tr:last-child td { border-bottom: 0; }

/* Rows where the compared columns say the same thing. The default styling
   makes column 2 dark and bold and every later column grey, which is right
   when the columns differ — but on a parity row it renders two identical
   values unequally, so a row whose whole purpose is to show the roles match
   ends up looking like another win. Here both sides get the same weight and
   colour, and neither is muted: the point is that they are equal, not that
   the row is unimportant. CSS cannot compare cell text, so the row is marked
   in the markup. */
.ed-table tr.ed-table-same td:nth-child(n+2) {
    font-weight: 500;
    color: #111827;
}
a.ed-col:hover h3 { color: #dc2626; }

.ed-col h3 {
    font-size: 1.0625rem;
    font-weight: 600;
    line-height: 1.35;
    margin: 0 0 0.75rem;
    transition: color 0.18s ease;
}

.ed-col p {
    margin: 0;
    color: #4b5563;
    font-size: 0.9688rem;
}

/* --- primitive: marked situation list --- */
.ed-marks {
    display: grid;
    gap: 2.25rem 4rem;
}

@media (min-width: 768px) {
    .ed-marks { grid-template-columns: 1fr 1fr; }
}

.ed-mark {
    border-left: 2px solid #dc2626;
    padding-left: 1.25rem;
    margin: 0;
    color: #374151;
    line-height: 1.75;
}

/* --- hero --- */
.ed-stats {
    display: flex;
    flex-wrap: wrap;
    gap: 3rem;
    margin: 0 0 2.75rem;
}

.ed-stat b {
    font-family: 'Montserrat', sans-serif;
    font-size: 1.5rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1;
    display: block;
}

.ed-stat span {
    font-family: 'Montserrat', sans-serif;
    font-size: 0.6875rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: #6b7280;
}

/* --- button --- */
.ed-btn {
    display: inline-block;
    background-color: #dc2626;
    color: #fff;
    text-decoration: none;
    font-family: 'Montserrat', sans-serif;
    font-weight: 600;
    font-size: 1rem;
    padding: 0.85rem 1.6rem;
    transition: background-color 0.18s ease;
}

.ed-btn:hover { background-color: #b91c1c; color: #fff; }

/* --- articles --- */
.ed-art {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.5rem;
    padding: 2rem 1rem;
    margin: 0 -1rem;
    text-decoration: none;
    color: inherit;
    transition: background-color 0.18s ease;
}

@media (min-width: 768px) {
    .ed-art {
        grid-template-columns: 5rem 1fr auto;
        gap: 1.75rem;
        align-items: center;
    }
}

.ed-art:hover { background-color: #fafafa; }
.ed-art:hover h3 { color: #dc2626; }

.ed-art img {
    width: 100%;
    height: 8rem;
    object-fit: cover;
    display: block;
    margin-bottom: 0.5rem;
}

@media (min-width: 768px) {
    .ed-art img { height: 5rem; margin-bottom: 0; }
}

.ed-art h3 {
    font-size: 1.0625rem;
    font-weight: 600;
    margin: 0 0 0.2rem;
    transition: color 0.18s ease;
}

.ed-art p {
    margin: 0;
    color: #6b7280;
    font-size: 0.9375rem;
}

.ed-art .ed-go {
    display: none;
    font-family: 'Montserrat', sans-serif;
    color: #d1d5db;
}

@media (min-width: 768px) {
    .ed-art .ed-go { display: block; }
}

/* --- testimonials restyle (keeps carousel JS contract) --- */
.ed-quote {
    font-size: 1.125rem;
    font-style: italic;
    line-height: 1.7;
    color: #111827;
    margin: 0 0 1rem;
}

@media (min-width: 768px) {
    .ed-quote { font-size: 1.25rem; }
}

/* Keep the hero (and its scroll indicator) inside the fold on short viewports.
   The indicator is anchored to the hero's bottom edge, so the hero must not
   outgrow calc(100vh - header).

   Qualified with the element (section.ed-hero, specificity 0,1,1) so these win
   against the Tailwind padding utilities on the same section no matter which
   stylesheet the build emits first. Every full-height hero must carry .ed-hero
   or it opts out of these guards and its chevrons drop below the fold. */
/* The hero is locked to 100vh minus the header, but its content is usually far
   shorter than that. Left alone the content top-aligns: it sits jammed under the
   header with a dead void above the scroll indicator. Centring it spreads the
   slack evenly above and below, so the hero breathes at both edges at any
   viewport height. The bottom padding reserves the strip the indicator sits in
   so centred content can never collide with it. */
@media (min-width: 768px) {
    section.ed-hero {
        display: flex;
        flex-direction: column;
        justify-content: center;
        padding-top: 4rem;
        padding-bottom: 7rem;
    }
}

@media (min-width: 768px) and (max-height: 820px) {
    section.ed-hero {
        padding-top: 2.5rem;
        padding-bottom: 6.5rem;
    }
}

/* Laptop viewports (~700-780px of usable height) are the common case, not an
   edge case: the hero has to fit its copy AND the indicator there. Tighten the
   frame rather than dropping the indicator — hiding it made the chevrons vanish
   on ordinary laptops. */
@media (min-width: 768px) and (max-height: 780px) {
    section.ed-hero {
        padding-top: 1.5rem;
        padding-bottom: 4.5rem;
    }

    section.ed-hero .ed-stats { margin-bottom: 1.5rem; }

    .ed-hero .ed-scroll { bottom: 2rem; }
}

@media (min-width: 768px) and (max-height: 700px) {
    section.ed-hero {
        padding-top: 1.5rem;
        padding-bottom: 4.5rem;
    }

    section.ed-hero .ed-stats { margin-bottom: 1.75rem; }
}

/* Below ~740px of viewport height the longest-copy hero (a two-line h1 over a
   three-line lede, e.g. fractional-cto-technical-debt) still overlapped the
   scroll chevrons. Spacing absorbs it, not type: the headline size is
   deliberately height-independent so a full-screen window and a windowed one
   render the same page identically. Placed after the 700px tier so it wins on
   source order at equal specificity. */
@media (min-width: 768px) and (max-height: 740px) {
    section.ed-hero {
        padding-top: 1rem;
        padding-bottom: 3.5rem;
    }

    section.ed-hero .ed-stats { margin-bottom: 1rem; }

    .ed-hero .ed-scroll { bottom: 1.75rem; }
}

/* The scroll indicator's distance from the fold. It is a system value, not a
   per-page utility: the chevrons animate 10px downward, so the clearance has to
   absorb that travel or they read as clipped at the animation's peak. On a tall
   viewport there is room to be generous; on a short one the hero copy needs the
   space more than the indicator does, so the offset tightens with it. */
.ed-hero .ed-scroll { bottom: 4rem; }

@media (max-height: 900px) {
    .ed-hero .ed-scroll { bottom: 3.25rem; }
}

@media (max-height: 820px) {
    .ed-hero .ed-scroll { bottom: 2.75rem; }
}


/* Testimonials sit inside the editorial column: the quote aligns with every
   other left edge on the page. Arrows sit below the quote — the track must
   stay clipped (8 slides x 100% wide) or the page scrolls sideways. */
.ed-section .testimonials-carousel {
    padding: 0;
    overflow: hidden;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

.ed-section .testimonials-track {
    order: -1;
    width: 100%;
}

.ed-section .carousel-button {
    position: static;
    transform: none;
    display: inline-flex;
    width: 40px;
    height: 40px;
    border-radius: 0;
    background-color: transparent;
    border: 1px solid #e5e7eb;
}

.ed-section .carousel-button:hover {
    border-color: #dc2626;
    background-color: transparent;
}

.ed-section .carousel-button:hover svg { stroke: #dc2626; }
.ed-section .carousel-button:active { transform: scale(0.95); }

/* Arrows lead the control row; the step dots need their own breathing room
   so the two controls don't read as one cluster. */
.ed-section .carousel-dots {
    margin-top: 0;
    margin-left: 1.75rem;
    align-items: center;
    align-self: center;
}

@media (max-width: 480px) {
    .ed-section .carousel-dots { margin-left: 1rem; }
}


/* Give the identity card enough width for the role to set on one line. */


/* Capability points: a footnote to the bio, so they sit a step below body
   copy. At 18px Lora they carried more weight than the identity beside them. */
.ed-about-points { list-style: none; margin: 0; padding: 0; }

.ed-about-points li + li { margin-top: 1.25rem; }

/* Beside the card the group centres against it; stacked on mobile it is a plain
   list with the same rhythm. These must stay at top level: nested inside the
   1024px query the mobile list lost its spacing entirely. */
@media (min-width: 1024px) {
    .ed-about-points {
        display: flex;
        flex-direction: column;
        justify-content: center;
        gap: 1.25rem;
        height: 100%;
    }

    .ed-about-points li + li { margin-top: 0; }
}

.ed-about-point {
    font-size: 1.125rem;
    line-height: 1.6;
}
/* About identity block — a personal card, not a panel of paragraphs.
   The name is the hero, set in wide-tracked caps; a thin red rule divides it
   from the role beneath, which is set smaller and tracked wider still. Contact
   detail is demoted to a single quiet line. Weights stay light so the block
   reads as a card rather than competing with the bio above it. */
.ed-ident {
    display: flex;
    align-items: center;
    gap: 1.75rem;
    background-color: #fff;
    border: 1px solid #e5e7eb;
    border-radius: 8px;
    padding: 2.25rem 1.75rem;
    /* the accent disc runs off the left edge and is cut by the card */
    overflow: hidden;
}

/* A second, larger disc sits behind the portrait in a pale red and breaks past
   its edge — the one bit of colour in the card, and the only thing that stops
   the photo reading as a plain avatar. */
.ed-ident-photo {
    position: relative;
    display: block;
    flex-shrink: 0;
}

.ed-ident-photo::before {
    content: '';
    position: absolute;
    /* Offset far enough that its right edge lands on the photo's, so it reads as
       a disc peeking out behind rather than a ring drawn around. */
    /* Same diameter as the portrait, pushed far enough left that the two circles
       only just overlap and the disc is clipped by the card edge. Fitted to the
       reference by measuring its luminance steps, not by eye. */
    width: 100%;
    height: 100%;
    top: -20%;
    left: -48%;
    border-radius: 9999px;
    background-color: rgba(220, 38, 38, 0.04);
}

.ed-ident-photo img {
    position: relative;
    z-index: 1;
}

.ed-ident img {
    width: 5.5rem;
    height: 5.5rem;
    border-radius: 9999px;
    object-fit: cover;
    flex-shrink: 0;
}

.ed-ident-name {
    font-family: 'Montserrat', sans-serif;
    font-size: 1.0625rem;
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: #111827;
    line-height: 1.45;
    margin: 0;
}

.ed-ident-rule {
    width: 3rem;
    height: 1px;
    background-color: #dc2626;
    margin: 0.85rem 0;
}

.ed-ident-role {
    font-family: 'Montserrat', sans-serif;
    font-size: 0.6875rem;
    font-weight: 500;
    letter-spacing: 0.24em;
    text-transform: uppercase;
    color: #6b7280;
    margin: 0;
}

.ed-ident-place {
    font-family: 'Montserrat', sans-serif;
    font-size: 0.8125rem;
    font-weight: 400;
    color: #4b5563;
    margin: 0.75rem 0 0;
}

.ed-ident-meta {
    font-family: 'Montserrat', sans-serif;
    font-size: 0.75rem;
    font-weight: 400;
    color: #9ca3af;
    margin: 1.1rem 0 0;
}

.ed-ident-link {
    color: #dc2626;
    font-weight: 500;
    text-decoration: none;
}

.ed-ident-link:hover { text-decoration: underline; }

@media (min-width: 1024px) {
    



/* The card holds the photo and takes the wider column; the points sit in the
   narrower one and wrap. That is what makes the two blocks read as equal
   masses — flipping it left both blocks small and the row slack. */
/* Sized to the content: the card needs ~454px to keep the tracked name on one
   line, the points ~428px to keep each on one. Both fit in the 920px available,
   so neither wraps and the two columns end level. */
.ed-about-cols { grid-template-columns: 1.05fr 1fr; }
}

/* The headline uses the column, like everything else on the page. Capped at
   52rem it stopped 128px short of where every h2, grid and eyebrow below it
   ends, so the hero read as a narrower page than the one under it — and
   narrower than its own eyebrow and stats, which were already full width.

   `balance` does the job the cap was doing. Left to wrap naturally the
   homepage h1 set as a 902px line over a 239px one: the width was used but
   the rag was lopsided. Balancing evens the lines, and since it only ever
   shortens the LONGEST line for a given line count, a headline that fits on
   one line still fills the column. Browsers without support fall back to the
   natural wrap — a worse rag, not a broken layout. */
.ed-hero-h1 {
    max-width: none;
    text-wrap: balance;
}

/* Balance evens the rag but it also SHORTENS the longest line, which left the
   60px headline setting narrower lines (636px) than its own lede (712px) —
   the subtitle out-measuring the title. The column is 960px wide at every
   viewport past 1024 (it is capped at 64rem), so one step up in size fixes it
   everywhere: at 80px the balanced lines run ~850px and the headline commands
   the column again. Beats .md\:text-6xl on specificity regardless of source
   order. */
@media (min-width: 1280px) {
    .ed-hero-h1 { font-size: 4.5rem; }
}

/* 4.5rem is sized for a hero that gets the whole 64rem column. Fifteen pages
   split their hero into two columns and hand the headline roughly half of it —
   456px at a 1470px window — where 72px set "Hire a / Fractional / CTO" across
   three lines. Type is sized to its measure, not to the page, so a narrower
   measure takes a smaller size. */
@media (min-width: 1280px) {
    .ed-hero:has(.md\:grid-cols-2) .ed-hero-h1 { font-size: 3rem; }
}

/* Laptops are the common case, not an edge case: at 80px the taller headline
   plus the 5rem header pushes the hero into its scroll chevrons on a short
   viewport. Step it back down rather than letting the copy collide. */
/* Deliberately NOT height-dependent. An earlier version stepped this down at
   max-height 860 and 760, which meant the same page at the same width rendered
   a different headline depending on whether the browser was full-screen or had
   a toolbar — two windows side by side on one machine disagreeing. Type size
   is a function of the column's width, and the column is 64rem at every
   viewport past 1024, so one size is correct everywhere. Short viewports are
   absorbed by the hero's padding guards below, not by resizing the type. */

/* The headline fills the column; the lede must not. They are different kinds
   of type: the h1 is display type, where spanning the full 64rem reads as
   confident, while the lede is body copy, where 960px is ~95 characters a
   line — well past the 45-75 a reader tracks comfortably. 52rem is ~69, at
   the upper end but honest, and it closes most of the 288px gap the old
   42rem `max-w-2xl` left.

   One rule for all 16 hero pages. Only the two homepages carried `max-w-2xl`
   in the markup; the other 14 had no measure at all and were running the full
   960px. */
.ed-hero-h1 + p { max-width: 52rem; }

/* Article cards lead with the image. */
.ed-card-media {
    aspect-ratio: 3 / 2;
    overflow: hidden;
    background-color: #f3f4f6;
}

.ed-card-media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 0.4s ease;
}

.ed-card:hover .ed-card-media img { transform: scale(1.04); }

/* The featured article spans both columns, so a 3:2 crop would be ~680px tall
   and push everything else under the fold. A wider crop keeps the image
   prominent without eating the viewport. It only applies once the card actually
   spans two columns: single-column, 21:9 makes the lead image the SHORTEST on
   the page, which inverts the hierarchy it exists to create. */
@media (min-width: 768px) {
    .ed-card-media--wide { aspect-ratio: 21 / 9; }
}

/* Related articles are secondary navigation at the foot of a piece, not the
   main event: a shallower crop keeps the thumbnail readable while stopping the
   card from rivalling the article it sits under. */
.ed-card-media--compact { aspect-ratio: 16 / 9; }

/* Blog articles fill the same 64rem spine as the header and every landing
   page, so the article column and the menu share both edges. No extra reading
   measure: a narrower cap made the content stop short of the nav above it. */

@media (prefers-reduced-motion: reduce) {
    .ed-card-media img { transition: none; }
    .ed-card:hover .ed-card-media img { transform: none; }
}

/* ── Header ──────────────────────────────────────────────────────
   Sticky, and aligned to the same column as the page so the logo sits
   on the left edge that every heading below it shares. */
.ed-header {
    position: sticky;
    top: 0;
    z-index: 50;
    background-color: #fff;
    /* Transparent rather than absent: the border box keeps the same 1px in
       both states, so the header never changes height and the hero's
       calc(100vh - 4rem) stays honest. */
    border-bottom: 1px solid transparent;
    transition: border-color 0.2s ease, background-color 0.2s ease;
}

/* At rest the bar floats on the white hero with no rule under it. Once the
   page scrolls it sits over content and has to separate itself, so it earns
   the hairline and a translucent, blurred ground. Toggled by
   initHeaderScrollState() in page-enhancements.js. */
.ed-header--scrolled {
    border-bottom-color: #e5e7eb;
    background-color: rgba(255, 255, 255, 0.85);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
}

/* HEADER HEIGHT IS SET IN THREE PLACES AND THEY MUST AGREE:
     1. here,
     2. DEFAULT_OFFSET in page-enhancements.js — the hero is sized
        calc(100vh - DEFAULT_OFFSET), so a mismatch pushes the hero past the
        fold and drops its scroll chevrons out of view,
     3. `fixedHeight` in initHeaders() in the same file, which sets height,
        min-height and max-height INLINE on the <header> as an anti-CLS guard.
   (3) is the one that bites: inline styles beat this rule, and initHeaders()
   only runs in dev — the build inlines the partials and strips the call — so
   changing this value alone leaves dev pinned at the old height while
   production uses the new one, and the two stop matching. */
.ed-header-inner {
    height: 5rem;
    display: flex;
    align-items: center;
}

/* Past 1280px the bar spans the viewport with symmetric 2rem gutters instead
   of sitting inside the 64rem column, so the brand and nav reach the outer
   margins rather than bunching mid-screen on a wide display. 2rem is the
   gutter .ed-wrap already uses for its own padding, so the inset is a system
   value rather than a new number.

   The brand therefore does NOT sit on the content spine here — at 1920 it is
   ~416px left of the h1 below it. That is the deliberate trade: the spine is
   ~480px from the viewport edge while a full-bleed gutter is ~32px, so a bar
   can have the brand on the spine OR symmetric gutters, never both. Keeping
   the brand on the spine and moving only the nav produces a lopsided
   480px/32px split. Below 1280px the bar returns to the column. */
@media (min-width: 1280px) {
    .ed-wrap.ed-header-inner {
        max-width: none;
        padding-left: 2rem;
        padding-right: 2rem;
    }

    .ed-nav { gap: 2.25rem; }
}

.ed-brand {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    text-decoration: none;
    color: #111827;
    font-family: 'Montserrat', sans-serif;
    /* Nameplate, not bolded body text. Montserrat is self-hosted at 400 and
       600 only, so weight alone offered exactly two options: 600 read too
       heavy and 400 too light. Size and tracking solve it instead — weight
       stops reading as heaviness once the letters have air.

       This is the site's own vocabulary, not a new idea: .ed-eyebrow already
       sets uppercase Montserrat 600 on open tracking above every h2. The
       wordmark now uses the same device at a larger size, so the header
       borrows nothing from outside the system. */
    font-size: 0.875rem;
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    white-space: nowrap;
}

.ed-burger {
    margin-left: auto;
    color: #4b5563;
    background: none;
    border: 0;
    cursor: pointer;
}

.ed-nav {
    display: none;
    margin-left: auto;
    align-items: center;
    gap: 1.75rem;
}

@media (min-width: 768px) {
    .ed-nav { display: flex; }
}

.ed-nav > a:not(.ed-nav-cta) {
    position: relative;
    font-family: 'Montserrat', sans-serif;
    font-size: 0.875rem;
    font-weight: 500;
    color: #374151;
    text-decoration: none;
    padding: 0.35rem 0;
}

/* the underline grows from the left rather than just recoloring */
.ed-nav > a:not(.ed-nav-cta)::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    height: 1px;
    width: 100%;
    background-color: #dc2626;
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.22s ease;
}

.ed-nav > a:not(.ed-nav-cta):hover { color: #dc2626; }
.ed-nav > a:not(.ed-nav-cta):hover::after { transform: scaleX(1); }

.ed-nav-cta {
    background-color: #dc2626;
    color: #fff;
    font-family: 'Montserrat', sans-serif;
    font-size: 0.875rem;
    font-weight: 600;
    padding: 0.5rem 1.1rem;
    border-radius: 0.5rem;
    text-decoration: none;
    transition: background-color 0.18s ease;
}

.ed-nav-cta:hover { background-color: #b91c1c; color: #fff; }

/* Lives inside the sticky header so it opens under the bar at any scroll
   position, not a thousand pixels up the page. */
.ed-mobile-nav {
    background-color: #fff;
    border-top: 1px solid #e5e7eb;
    border-bottom: 1px solid #e5e7eb;
    padding: 0.5rem 0 1rem;
}

.ed-mobile-nav a {
    display: block;
    padding: 0.6rem 0;
    font-family: 'Montserrat', sans-serif;
    font-size: 0.9375rem;
    font-weight: 500;
    color: #374151;
    text-decoration: none;
}

.ed-mobile-nav a:hover { color: #dc2626; }
.ed-mobile-cta { color: #dc2626 !important; font-weight: 600 !important; }

@media (prefers-reduced-motion: reduce) {
    .ed-nav > a::after { transition: none; }
    .ed-header { transition: none; }
}

/* ── Footer ──────────────────────────────────────────────────────
   Given room to be a real sitemap block instead of one cramped line. */
.ed-footer {
    border-top: 1px solid #e5e7eb;
    padding: 3.5rem 0 2rem;
    background-color: #fff;
}

.ed-footer-top {
    display: grid;
    gap: 2.5rem;
}

@media (min-width: 768px) {
    .ed-footer-top {
        grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
        gap: 4rem;
    }
}

.ed-footer-brand p {
    margin: 1rem 0 0;
    color: #4b5563;
    font-size: 0.9375rem;
    max-width: 26rem;
}

.ed-footer-cta {
    display: inline-block;
    margin-top: 1.1rem;
    color: #dc2626;
    font-family: 'Montserrat', sans-serif;
    font-size: 0.875rem;
    font-weight: 600;
    text-decoration: none;
}

.ed-footer-cta:hover { text-decoration: underline; }

.ed-footer-links {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 2rem;
}

.ed-footer-links .ed-eyebrow { margin-bottom: 0.75rem; }

.ed-footer-links a {
    display: block;
    padding: 0.3rem 0;
    font-family: 'Montserrat', sans-serif;
    font-size: 0.875rem;
    font-weight: 500;
    color: #4b5563;
    text-decoration: none;
}

.ed-footer-links a:hover { color: #dc2626; }

.ed-footer-legal {
    margin: 3rem 0 0;
    padding-top: 1.5rem;
    border-top: 1px solid #e5e7eb;
    font-size: 0.8125rem;
    color: #6b7280;
}

/* Article + contents rail. The grid still fills the full 64rem spine, so the
   article's outer edges keep matching the header; the reading column narrows to
   a comfortable measure and the width it gives up is occupied by the contents
   rather than left as margin. Below lg there is no room for a rail, so the
   prose takes the full column and the contents are hidden — they are an aid to
   scanning, not content. */
.article-layout {
    display: grid;
    gap: 3rem;
}

.article-toc { display: none; }

@media (min-width: 1024px) {
    .article-layout {
        grid-template-columns: minmax(0, 1fr) 14rem;
    }

    /* The grid item must stay stretched: with align-items/self: start it
       shrinks to content height, leaving position: sticky no room to move
       inside its containing block, and the rail scrolls away. Stick the inner
       wrapper instead. */
    .article-toc { display: block; }

    .article-toc-inner {
        position: sticky;
        /* clears the sticky site header */
        top: 6rem;
    }
}

.article-toc ul {
    list-style: none;
    margin: 0.75rem 0 0;
    padding: 0;
    border-left: 1px solid #e5e7eb;
}

.article-toc li { margin: 0; }

.article-toc a {
    display: block;
    padding: 0.4rem 0 0.4rem 1rem;
    margin-left: -1px;
    border-left: 2px solid transparent;
    font-family: 'Montserrat', sans-serif;
    font-size: 0.8125rem;
    font-weight: 500;
    line-height: 1.45;
    color: #6b7280;
    text-decoration: none;
    transition: color 0.2s ease, border-color 0.2s ease;
}

.article-toc a:hover { color: #111827; }

.article-toc a.is-current {
    color: #111827;
    border-left-color: #dc2626;
}

/* Nothing on these pages is meant to scroll sideways. `clip` rather than
   `hidden`: `hidden` would make <body> a scroll container, which breaks
   position: sticky on the header. */
html,
body {
    max-width: 100%;
    overflow-x: clip;
}

/* A heading followed straight by content (no lede paragraph) needs the gap the
   lede would otherwise provide -- .ed-section h2 only carries 1rem of its own. */
.ed-section h2 + div,
.ed-section h2 + ul,
.ed-section h2 + ol,
.ed-section h2 + article,
.ed-section h2 + figure,
.ed-section h2 + .grid,
.ed-section h2 + .ed-rows,
.ed-section h2 + .ed-cols,
.ed-section h2 + .ed-marks {
    margin-top: 2.5rem;
}

/* A quote supporting the case study above it, not a third card competing with
   the two around it: no fill, no radius, just the red rule used elsewhere. */
.ed-pullquote {
    border-left: 2px solid #dc2626;
    padding: 0.25rem 0 0.25rem 1.5rem;
    margin: 2.5rem 0;
}

.ed-pullquote blockquote {
    font-size: 1.125rem;
    font-style: italic;
    line-height: 1.7;
    color: #374151;
    margin: 0;
}

.ed-pullquote figcaption { margin-top: 1rem; }

/* A reference from the client of the case study it closes: set inside the card,
   separated by a rule rather than boxed again. */
.ed-cardquote {
    margin: 2rem 0 0;
    padding-top: 1.75rem;
    border-top: 1px solid #e5e7eb;
}

.ed-cardquote blockquote {
    margin: 0;
    font-size: 1.0625rem;
    font-style: italic;
    line-height: 1.7;
    color: #374151;
}

.ed-cardquote figcaption {
    margin-top: 0.85rem;
    font-family: 'Montserrat', sans-serif;
    font-size: 0.875rem;
}

.ed-cardquote figcaption span {
    display: block;
    font-size: 0.8125rem;
    color: #6b7280;
    margin-top: 0.15rem;
}

/* Follow-on note: the small aside that points somewhere else after a block
   ("Explore other case studies…", "Want to start smaller?…"). One format. */
.ed-note {
    margin: 1.5rem 0 0;
    font-size: 0.9375rem;
    color: #4b5563;
}

/* ── Sequence steps ──────────────────────────────────────────────
   Numbered because the order is load-bearing: the audit comes first
   and everything after it is optional. */
.ed-step {
    font-family: 'Montserrat', sans-serif;
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.18em;
    color: #dc2626;
    margin: 0 0 0.75rem;
}

/* ── Keep / fix / rewrite ────────────────────────────────────────
   Weighted the way the copy describes it: keeping and fixing are the
   common outcomes, a rewrite is the exception you argue for. */
.ed-triage { position: relative; }

.ed-triage-label {
    font-family: 'Montserrat', sans-serif;
    font-size: 1.125rem;
    font-weight: 700;
    margin: 0 0 0.5rem;
}

.ed-triage--keep { border-top: 3px solid #9ca3af; }
.ed-triage--keep .ed-triage-label { color: #4b5563; }

.ed-triage--fix { border-top: 3px solid #dc2626; }
.ed-triage--fix .ed-triage-label { color: #dc2626; }

.ed-triage--rewrite { border-top: 3px dashed #d1d5db; }
.ed-triage--rewrite .ed-triage-label { color: #6b7280; }

.ed-triage--rewrite::after {
    content: "the exception";
    display: block;
    margin-top: 0.85rem;
    font-family: 'Montserrat', sans-serif;
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: #9ca3af;
}
