/* =============================================================================
   InvestProp — testimonial wall (2026 rebuild)
   -----------------------------------------------------------------------------
   Replaces `comments.css` and the Swiper row it styled. Used by
   `site/index/comment.blade.php`, which is shared by the home page AND the
   plans page, so everything is scoped to `.tw` — the section's own class — and
   never to a body class.

   Shape of the section: a rating summary panel beside a wall of three columns
   that drift vertically in alternating directions, pausing on hover or focus so
   a reader can actually finish a sentence.

   Sept 2026: like/dislike removed (client request); ratings are 4 / 4.5 / 5
   only, so the star rows must render a true half star; the "leave a review"
   form gained an optional profile photo and a three-choice rating picker.

   Conventions this file must respect (see the site design system):
     • dark is the DEFAULT theme (`html.dark`); light is the opt-in override,
       and neither compiled sheet sets a global text colour — every block here
       declares its own.
     • RTL is the default direction; logical properties throughout.
   ========================================================================== */

.tw {
    --tw-primary: #007BFF;
    --tw-primary-2: #1C8AFF;
    --tw-cyan: #5ED2EC;
    --tw-mint: #3DD68C;
    --tw-gold: #FFB800;
    --tw-rose: #F2555A;

    --tw-surface: rgba(7, 20, 37, .72);
    --tw-surface-2: rgba(10, 26, 47, .92);
    --tw-inset: rgba(255, 255, 255, .03);
    --tw-line: rgba(141, 196, 255, .14);
    --tw-line-strong: rgba(141, 196, 255, .3);
    --tw-text: #EAF2FF;
    --tw-text-2: #C3D4EA;
    --tw-muted: #8FA5C2;
    --tw-track: rgba(141, 196, 255, .14);
    --tw-link: #8DC4FF;
    --tw-amber-text: #FFC53D;
    --tw-error: #F2555A;
    --tw-success: #3DD68C;

    --tw-grad: linear-gradient(94.98deg, #007BFF 4.01%, #1C8AFF 103.03%);
    --tw-shadow: 0 30px 80px -40px rgba(0, 0, 0, .9);

    position: relative;
    margin-top: 96px;
    /* Explicitly visible, overriding `.comments-section { overflow: hidden;
       overflow-y: auto }` in mainPage.css. An overflow value other than visible
       here makes this element the sticky panel's scroll container, and since it
       never scrolls the panel would silently stop following the wall. The
       columns are already clipped by `.tw-wall`, and the orbs by `.tw__bg`. */
    overflow: visible;
}

html:not(.dark) .tw {
    --tw-surface: rgba(255, 255, 255, .82);
    --tw-surface-2: #FFFFFF;
    --tw-inset: rgba(10, 40, 80, .03);
    --tw-line: rgba(0, 72, 153, .12);
    --tw-line-strong: rgba(0, 72, 153, .24);
    --tw-text: #0A1A30;
    --tw-text-2: #2B4463;
    --tw-muted: #5D7492;
    --tw-track: rgba(0, 72, 153, .1);
    --tw-link: #0B62C4;
    /* Gold text on white is ~1.9:1 — selected-state numerals darken instead. */
    --tw-amber-text: #A86400;
    --tw-error: #C42B31;
    --tw-success: #158A52;
    --tw-shadow: 0 26px 60px -38px rgba(10, 40, 80, .45);
}

.tw__bg {
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    overflow: hidden;
}

.tw__bg span {
    position: absolute;
    border-radius: 50%;
    filter: blur(110px);
    opacity: .4;
}

html:not(.dark) .tw__bg span { opacity: .22; }

.tw__bg span:nth-child(1) {
    inset-inline-start: -10%;
    top: 8%;
    width: 520px;
    height: 520px;
    background: radial-gradient(circle, rgba(0, 123, 255, .5), rgba(0, 123, 255, 0) 66%);
}

.tw__bg span:nth-child(2) {
    inset-inline-end: -8%;
    bottom: 4%;
    width: 460px;
    height: 460px;
    background: radial-gradient(circle, rgba(94, 210, 236, .3), rgba(94, 210, 236, 0) 66%);
}

.tw > .container-fluid { position: relative; z-index: 1; }

/* Numerals sit inside Persian sentences; isolate so "4.8" and "۱۲۸" never
   reorder against the surrounding RTL run. */
.tw .tw-num {
    font-family: dana, yekanbakh, sans-serif;
    font-variant-numeric: tabular-nums;
    direction: ltr;
    unicode-bidi: isolate;
}

/* Screen-reader-only text (e.g. "stars" inside the rating choices). */
.tw .tw-sr {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* -----------------------------------------------------------------------------
   Header
   -------------------------------------------------------------------------- */

.tw-head {
    max-width: 720px;
    margin: 0 auto 40px;
    text-align: center;
}

.tw-head__eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 14px;
    border-radius: 999px;
    border: 1px solid var(--tw-line-strong);
    background: color-mix(in srgb, var(--tw-primary) 10%, transparent);
    color: #8DC4FF;
    font-size: 13px;
    font-weight: 700;
    margin-bottom: 16px;
}

html:not(.dark) .tw-head__eyebrow { color: #0B62C4; }

.tw-head__title {
    margin: 0;
    font-size: clamp(24px, 3.4vw, 40px);
    font-weight: 900;
    line-height: 1.35;
    color: var(--tw-text);
}

.tw-head__title b {
    background: linear-gradient(96deg, var(--tw-primary-2), var(--tw-cyan));
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

html:not(.dark) .tw-head__title b {
    background: linear-gradient(96deg, #0069DC, #17A9C7);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

.tw-head__sub {
    margin: 14px 0 0;
    font-size: 14.5px;
    line-height: 2.1;
    color: var(--tw-muted);
}

/* -----------------------------------------------------------------------------
   Layout: summary panel + wall
   -------------------------------------------------------------------------- */

.tw-layout {
    display: grid;
    gap: 24px;
    align-items: start;
}

@media (min-width: 992px) {
    .tw-layout { grid-template-columns: minmax(300px, 360px) minmax(0, 1fr); }
}

/* -----------------------------------------------------------------------------
   Rating summary
   -------------------------------------------------------------------------- */

.tw-summary {
    position: relative;
    padding: 28px 24px;
    border-radius: 24px;
    border: 1px solid var(--tw-line);
    background: var(--tw-surface-2);
    backdrop-filter: blur(26px);
    box-shadow: var(--tw-shadow);
    overflow: hidden;
}

.tw-summary::before {
    content: "";
    position: absolute;
    inset-inline: 18%;
    top: 0;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(141, 196, 255, .55), transparent);
}

/* NOT sticky: `html`/`body` carry `overflow-x: hidden` site-wide, which forces
   the used `overflow-y` to auto and makes body a scroll container — sticky
   silently resolves against it and never travels. (The desktop menu hit the
   same wall and went `position: fixed`.) Instead the panel stretches to the
   wall's height and its content spreads, so the column has no dead space. */
@media (min-width: 992px) {
    .tw-layout { align-items: stretch; }

    /* The blocks are spaced by `gap`, so the auto margin below can only ever
       ADD space — with the form open the panel outgrows the wall and the
       spacing stays 22px instead of collapsing to zero. */
    .tw-summary {
        display: flex;
        flex-direction: column;
        gap: 22px;
    }

    .tw .tw-summary > .tw-dist,
    .tw .tw-summary > .tw-faces { margin-top: 0; }

    /* (0,3,0) on purpose: the base `.tw .comment-form-wrapper` margin further
       down is (0,2,0) and, being later, used to win — the CTA floated
       mid-panel with dead space under it instead of meeting the wall's foot. */
    .tw .tw-summary > .comment-form-wrapper { margin-top: auto; }
}

.tw-score {
    display: flex;
    align-items: center;
    gap: 16px;
    padding-bottom: 20px;
    border-bottom: 1px dashed var(--tw-line);
}

.tw-score__value {
    font-size: 52px;
    font-weight: 900;
    line-height: 1;
    background: linear-gradient(150deg, var(--tw-gold), #FF8A3D);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

.tw-score__meta { min-width: 0; }

.tw-score__count {
    margin: 6px 0 0;
    font-size: 13px;
    font-weight: 600;
    color: var(--tw-muted);
}

/* --- star row: two stacked layers, the top one clipped to --tw-fill ---------
   Ratings are 4 / 4.5 / 5, so the fill is 80 / 90 / 100 % and 4.5 must split
   the fifth star exactly in half. `letter-spacing` trails every glyph (the
   last one included), which puts a plain percentage half a gap past the
   glyph's centre — the gold layer is pulled back by that half gap. */
.tw-stars {
    --tw-ls: 2px;
    position: relative;
    display: inline-block;
    line-height: 1;
    font-size: 17px;
    letter-spacing: var(--tw-ls);
    /* The glyph run is LTR: a half-filled 4.5 must clip from the same side in
       both directions, or the "empty" stars end up on the wrong end. */
    direction: ltr;
    unicode-bidi: isolate;
    white-space: nowrap;
}

.tw-stars__off { color: var(--tw-track); }

.tw-stars__on {
    position: absolute;
    inset-block: 0;
    inset-inline-start: 0;
    left: 0;
    width: calc(var(--tw-fill, 100%) - var(--tw-ls) / 2);
    overflow: hidden;
    color: var(--tw-gold);
}

.tw-stars--lg { font-size: 22px; }

.tw-stars--sm {
    --tw-ls: 1px;
    font-size: 12.5px;
}

/* --- distribution bars (5 / 4.5 / 4) --- */
.tw-dist {
    list-style: none;
    margin: 20px 0 0;
    padding: 0;
    display: grid;
    gap: 11px;
}

.tw-dist li {
    display: grid;
    /* Fixed label and count tracks: each row is its own grid, so auto tracks
       would start the "4.5" bar later than the "5" bar. */
    grid-template-columns: 46px minmax(0, 1fr) 2.2em;
    align-items: center;
    gap: 10px;
    font-size: 12px;
    font-weight: 700;
    color: var(--tw-muted);
}

.tw-dist__star {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    color: var(--tw-text-2);
}

.tw-dist__star .tw-num {
    min-width: 22px;
    text-align: center;
}

.tw-dist__star i { font-size: 12px; color: var(--tw-gold); }

.tw-dist__bar {
    height: 6px;
    border-radius: 999px;
    background: var(--tw-track);
    overflow: hidden;
}

.tw-dist__bar i {
    display: block;
    height: 100%;
    border-radius: inherit;
    background: linear-gradient(90deg, var(--tw-gold), #FF8A3D);
    transition: width .8s cubic-bezier(.22, 1, .36, 1);
}

.tw-dist__count { text-align: center; }

/* --- who left them --- */
.tw-faces {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 22px;
    padding-top: 20px;
    border-top: 1px dashed var(--tw-line);
}

.tw-faces__stack {
    display: flex;
    flex: 0 0 auto;
    /* Row direction is fixed so the overlap always tucks the same way; without
       it the stack reverses under LTR and the shadows fall on the wrong side. */
    direction: ltr;
}

.tw-faces__stack img {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    object-fit: cover;
    border: 2px solid var(--tw-surface-2);
    margin-inline-start: -10px;
}

.tw-faces__stack img:first-child { margin-inline-start: 0; }

.tw-faces__text {
    font-size: 12.5px;
    font-weight: 600;
    line-height: 1.7;
    color: var(--tw-muted);
}

.tw-faces__text b { color: var(--tw-text); }

/* -----------------------------------------------------------------------------
   The wall
   -------------------------------------------------------------------------- */

.tw-wall {
    position: relative;
    display: grid;
    grid-template-columns: 1fr;
    gap: 18px;
    /* Column height is capped here rather than on the columns so all three
       share one fade edge. */
    height: min(680px, 76vh);
    overflow: hidden;
    -webkit-mask-image: linear-gradient(to bottom, transparent, #000 9%, #000 91%, transparent);
    mask-image: linear-gradient(to bottom, transparent, #000 9%, #000 91%, transparent);
}

@media (min-width: 768px) {
    .tw-wall { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1200px) {
    .tw-wall { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.tw-col { min-width: 0; }

.tw-col__inner {
    display: flex;
    flex-direction: column;
    animation: tw-drift-up var(--tw-dur, 60s) linear infinite;
    will-change: transform;
}

.tw-col--down .tw-col__inner { animation-name: tw-drift-down; }

/* The track holds two identical halves, so -50% lands exactly on the start of
   the second one. Card spacing is `margin-bottom`, NOT `gap`: with a gap the
   half-way point falls half a gap short and the loop visibly jumps. */
@keyframes tw-drift-up {
    from { transform: translateY(0); }
    to   { transform: translateY(-50%); }
}

@keyframes tw-drift-down {
    from { transform: translateY(-50%); }
    to   { transform: translateY(0); }
}

.tw-wall:hover .tw-col__inner,
.tw-wall:focus-within .tw-col__inner { animation-play-state: paused; }

@media (prefers-reduced-motion: reduce) {
    .tw-col__inner { animation: none; }
}

/* -----------------------------------------------------------------------------
   Testimonial card
   -------------------------------------------------------------------------- */

/* Doubled scope on purpose: `.comments-section .comment-card` in mainPage.css
   is (0,2,0) and still matches this element (the section keeps its old class
   for the plans page), so a bare `.tw-card` would lose its padding, radius and
   background to the old card styling. */
.tw .tw-card {
    position: relative;
    margin-bottom: 18px;
    padding: 22px 22px 18px;
    border-radius: 20px;
    border: 1px solid var(--tw-line);
    background: var(--tw-surface);
    backdrop-filter: blur(24px);
    box-shadow: var(--tw-shadow);
    overflow: hidden;
    transition: transform .35s cubic-bezier(.22, 1, .36, 1), border-color .3s ease;
}

.tw .tw-card:hover {
    transform: translateY(-4px);
    border-color: var(--tw-line-strong);
}

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

.tw .tw-card::before {
    content: "";
    position: absolute;
    inset-inline: 20%;
    top: 0;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(141, 196, 255, .5), transparent);
}

/* Oversized quote mark, sunk into the corner behind the text. */
.tw-card__mark {
    position: absolute;
    top: 10px;
    inset-inline-end: 16px;
    font-size: 46px;
    line-height: 1;
    color: var(--tw-primary);
    opacity: .13;
    pointer-events: none;
}

.tw-card__top {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 12px;
}

.tw-card__score {
    font-size: 12.5px;
    font-weight: 800;
    color: var(--tw-gold);
}

html:not(.dark) .tw-card__score { color: var(--tw-amber-text); }

.tw-card .comment-text {
    margin: 0;
    font-size: 13.5px;
    line-height: 2.15;
    color: var(--tw-text-2);
    /* Long testimonials would otherwise make one column tower over the others
       and stretch the loop out of sync. */
    display: -webkit-box;
    -webkit-line-clamp: 7;
    line-clamp: 7;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* --- admin reply --- */
.tw-card .comment-reply {
    margin-top: 14px;
    padding: 12px 14px;
    border-radius: 14px;
    border: 1px solid var(--tw-line);
    background: color-mix(in srgb, var(--tw-primary) 9%, transparent);
    font-size: 12.5px;
    line-height: 2;
    color: var(--tw-text-2);
    /* The reply is secondary to the testimonial; the border-inline-start reads
       as a quote rule in both directions. */
    border-inline-start: 3px solid var(--tw-primary-2);
}

.tw-card .comment-reply-label {
    display: block;
    margin-bottom: 4px;
    font-size: 11.5px;
    font-weight: 800;
    color: var(--tw-primary-2);
}

/* --- footer: author (opens the profile modal) --- */
.tw-card__foot {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 16px;
    padding-top: 14px;
    border-top: 1px dashed var(--tw-line);
}

.tw-who {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: 1 1 auto;
    min-width: 0;
    padding: 0;
    border: 0;
    background: none;
    text-align: start;
    cursor: pointer;
}

.tw-who:focus-visible {
    outline: 2px solid var(--tw-primary-2);
    outline-offset: 3px;
    border-radius: 10px;
}

.tw-who img {
    width: 38px;
    height: 38px;
    flex: 0 0 38px;
    border-radius: 50%;
    object-fit: cover;
    border: 1px solid var(--tw-line-strong);
}

.tw-who__meta { min-width: 0; }

.tw-who__name {
    display: flex;
    align-items: center;
    gap: 5px;
    margin: 0;
    font-size: 13.5px;
    font-weight: 800;
    color: var(--tw-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.tw-who__name .comment-verified {
    font-size: 14px;
    color: var(--tw-primary-2);
}

.tw-who__role {
    margin: 2px 0 0;
    font-size: 11.5px;
    font-weight: 600;
    color: var(--tw-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.tw-card:hover .tw-who__role { color: var(--tw-primary-2); }

/* "Open profile" hint at the far end of the row. `isax-arrow-left-2` is the
   site's forward arrow and site.css mirrors it under LTR, so no transform
   here (one would override that mirror). */
.tw-who__go {
    flex: 0 0 auto;
    margin-inline-start: auto;
    font-size: 16px;
    color: var(--tw-muted);
    opacity: .55;
    transition: color .25s ease, opacity .25s ease;
}

.tw-who:hover .tw-who__go,
.tw-who:focus-visible .tw-who__go {
    color: var(--tw-primary-2);
    opacity: 1;
}

/* -----------------------------------------------------------------------------
   Phone: no drift, a plain stack capped with a fade and a "show all" button
   -----------------------------------------------------------------------------
   Splitting the cards across three animated columns leaves only a third of them
   in the first column, so on phones the columns are unwrapped with
   `display: contents` and every card falls into one static run.
   -------------------------------------------------------------------------- */

@media (max-width: 767.98px) {
    .tw-wall {
        display: block;
        height: auto;
        max-height: 820px;
        -webkit-mask-image: none;
        mask-image: none;
    }

    .tw-wall.is-open { max-height: none; }

    .tw-col { display: contents; }

    .tw-col__inner {
        display: block;
        animation: none;
        transform: none;
    }

    /* The second half exists only to make the desktop loop seamless. */
    .tw-col__inner > [data-tw-dup] { display: none; }

    /* The fade has to land on the page background exactly, so these two values
       track `body`: #020915 dark, #F1F1F1 light. */
    .tw-wall::after {
        content: "";
        position: absolute;
        inset-inline: 0;
        bottom: 0;
        height: 140px;
        pointer-events: none;
        background: linear-gradient(to bottom, rgba(2, 9, 21, 0), #020915);
    }

    html:not(.dark) .tw-wall::after {
        background: linear-gradient(to bottom, rgba(241, 241, 241, 0), #F1F1F1);
    }

    .tw-wall.is-open::after { display: none; }
}

/* Base first, override second: declared the other way round the media query
   loses to the later rule and the button shows on desktop too. */
.tw-more {
    display: flex;
    justify-content: center;
    margin-top: 18px;
}

@media (min-width: 768px) {
    .tw-more { display: none; }
}

.tw-more button {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    height: 46px;
    padding-inline: 22px;
    border-radius: 14px;
    border: 1px solid var(--tw-line-strong);
    background: var(--tw-surface);
    backdrop-filter: blur(18px);
    font-size: 14px;
    font-weight: 800;
    color: var(--tw-text);
    cursor: pointer;
}

.tw-more button:hover {
    border-color: var(--tw-primary-2);
    background: color-mix(in srgb, var(--tw-primary) 12%, var(--tw-surface));
}

/* -----------------------------------------------------------------------------
   Empty state
   -------------------------------------------------------------------------- */

.tw-empty {
    padding: 40px 28px;
    border-radius: 20px;
    border: 1px dashed var(--tw-line-strong);
    background: var(--tw-surface);
    text-align: center;
    font-size: 14px;
    line-height: 2;
    color: var(--tw-muted);
}

/* =============================================================================
   "Leave a comment" — collapsed inside the summary panel
   -----------------------------------------------------------------------------
   The element ids and data hooks below (#commentForm, [data-comment-form-toggle],
   .comment-submit, .comment-form-message.is-success/.is-error,
   [data-comment-length], [data-avatar-picker] + [data-avatar-*]) are the
   contract with comments.js. Renaming any of them silently breaks submission.
   ========================================================================== */

.tw .comment-form-wrapper {
    margin-top: 22px;
    padding-top: 20px;
    border-top: 1px dashed var(--tw-line);
}

.tw .comment-form-toggle {
    width: 100%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    height: 50px;
    border-radius: 14px;
    border: 1px solid transparent;
    background: var(--tw-grad);
    color: #fff;
    font-size: 14.5px;
    font-weight: 800;
    cursor: pointer;
    box-shadow: 0 12px 34px -14px rgba(0, 123, 255, .9);
    transition: transform .2s ease, box-shadow .25s ease;
}

.tw .comment-form-toggle:hover {
    transform: translateY(-2px);
    box-shadow: 0 16px 40px -14px rgba(0, 123, 255, 1);
}

.tw .comment-form-toggle i { font-size: 18px; }

.tw .comment-form-toggle[aria-expanded="true"] {
    background: var(--tw-inset);
    color: var(--tw-text);
    border-color: var(--tw-line-strong);
    box-shadow: none;
}

.tw .comment-form { margin-top: 16px; }

.tw .comment-form-grid { display: grid; gap: 12px; }

@media (min-width: 480px) and (max-width: 991.98px) {
    .tw .comment-form-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.tw .comment-field { margin-bottom: 12px; }

/* Direct-child labels only: the photo picker and the rating choices nest
   labels of their own that must not inherit the block field-label look. */
.tw .comment-field > label,
.tw .comment-field > .tw-rate__legend {
    display: block;
    margin-bottom: 6px;
    font-size: 12.5px;
    font-weight: 700;
    color: var(--tw-text-2);
}

/* Text fields only — radios and the file input are styled by their widgets. */
.tw .comment-field input[type="text"],
.tw .comment-field textarea {
    width: 100%;
    padding: 11px 14px;
    border-radius: 12px;
    border: 1px solid var(--tw-line);
    background: var(--tw-inset);
    font-size: 13.5px;
    color: var(--tw-text);
    transition: border-color .25s ease, background-color .25s ease;
}

.tw .comment-field input[type="text"]::placeholder,
.tw .comment-field textarea::placeholder { color: var(--tw-muted); }

.tw .comment-field input[type="text"]:focus,
.tw .comment-field textarea:focus {
    outline: none;
    border-color: var(--tw-primary-2);
    background: color-mix(in srgb, var(--tw-primary) 8%, var(--tw-inset));
}

.tw .comment-field textarea { resize: vertical; min-height: 96px; }

.tw .comment-counter {
    display: block;
    margin-top: 5px;
    text-align: end;
    font-size: 11px;
    color: var(--tw-muted);
}

/* --- profile photo picker --------------------------------------------------
   A dashed drop target: circular live preview (the default avatar until a
   photo is chosen — exactly what the card will show), a camera badge, and
   choose / remove buttons. The real <input type=file> is visually hidden but
   stays focusable; its focus ring is drawn on the "choose" button. */
.tw .tw-photo {
    position: relative;
    display: flex;
    align-items: center;
    gap: 14px;
    margin-bottom: 14px;
    padding: 12px 14px;
    border-radius: 16px;
    border: 1px dashed var(--tw-line-strong);
    background: var(--tw-inset);
    transition: border-color .2s ease, background-color .2s ease;
}

.tw .tw-photo.has-photo {
    border-style: solid;
    border-color: var(--tw-line);
}

.tw .tw-photo.is-dragover {
    border-style: solid;
    border-color: var(--tw-primary-2);
    background: color-mix(in srgb, var(--tw-primary) 10%, transparent);
}

/* (0,3,0): beats the direct-child field-label rule above. */
.tw .tw-photo > .tw-photo__frame {
    position: relative;
    display: block;
    flex: 0 0 64px;
    width: 64px;
    height: 64px;
    margin: 0;
    border-radius: 50%;
    cursor: pointer;
}

.tw .tw-photo__img {
    display: block;
    width: 100%;
    height: 100%;
    border-radius: 50%;
    object-fit: cover;
    /* Zero-blur rings, not a drop shadow: reads as an outline in both themes. */
    box-shadow: 0 0 0 1px var(--tw-line-strong);
    transition: box-shadow .2s ease, filter .2s ease;
}

.tw .tw-photo.has-photo .tw-photo__img {
    box-shadow: 0 0 0 2px var(--tw-surface-2), 0 0 0 4px var(--tw-primary-2);
}

.tw .tw-photo__frame:hover .tw-photo__img { filter: brightness(1.08); }

.tw .tw-photo__badge {
    position: absolute;
    bottom: -3px;
    inset-inline-end: -3px;
    display: grid;
    place-items: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    border: 2px solid var(--tw-surface-2);
    background: var(--tw-grad);
    color: #fff;
    font-size: 13px;
    line-height: 1;
}

.tw .tw-photo__body {
    display: grid;
    gap: 2px;
    flex: 1 1 auto;
    min-width: 0;
}

.tw .tw-photo__title {
    font-size: 12.5px;
    font-weight: 700;
    color: var(--tw-text-2);
}

.tw .tw-photo__hint {
    font-size: 11px;
    line-height: 1.7;
    color: var(--tw-muted);
    overflow-wrap: anywhere;
}

.tw .tw-photo__hint.is-error {
    color: var(--tw-error);
    font-weight: 700;
}

/* The chosen file's "name · size" — Latin text in a Latin-digit face (the
   Persian body face draws 0-9 as ۰-۹, which would misspell file names). */
.tw .tw-photo__file {
    display: inline-flex;
    gap: 4px;
    max-width: 100%;
    vertical-align: bottom;
    white-space: nowrap;
    font-family: dana, yekanbakh, sans-serif;
    color: var(--tw-text-2);
}

/* A long file name gives way; the size after it always stays visible. */
.tw .tw-photo__fname {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

.tw .tw-photo__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin-top: 6px;
}

.tw .tw-photo .tw-photo__input {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip-path: inset(50%);
    opacity: 0;
}

.tw .tw-photo .tw-photo__btn {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 30px;
    margin: 0;
    padding-inline: 11px;
    border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--tw-primary-2) 42%, transparent);
    background: color-mix(in srgb, var(--tw-primary) 14%, transparent);
    font-size: 12px;
    font-weight: 800;
    line-height: 1;
    color: var(--tw-link);
    white-space: nowrap;
    cursor: pointer;
    transition: background-color .2s ease, border-color .2s ease, color .2s ease;
}

.tw .tw-photo .tw-photo__btn[hidden] { display: none; }

.tw .tw-photo .tw-photo__btn i { font-size: 14px; }

.tw .tw-photo .tw-photo__btn:hover {
    border-color: var(--tw-primary-2);
    background: color-mix(in srgb, var(--tw-primary) 22%, transparent);
}

.tw .tw-photo .tw-photo__input:focus-visible + .tw-photo__btn,
.tw .tw-photo .tw-photo__btn:focus-visible {
    outline: 2px solid var(--tw-primary-2);
    outline-offset: 2px;
}

.tw .tw-photo .tw-photo__btn--remove {
    border-color: var(--tw-line);
    background: transparent;
    color: var(--tw-muted);
}

.tw .tw-photo .tw-photo__btn--remove:hover {
    border-color: color-mix(in srgb, var(--tw-error) 45%, transparent);
    background: color-mix(in srgb, var(--tw-error) 10%, transparent);
    color: var(--tw-error);
}

/* --- rating: exactly three choices, 4 / 4.5 / 5 ------------------------------
   Native radios (visually hidden) inside label tiles, so the group is one tab
   stop and the arrow keys move the choice. Each tile shows its own star row
   through the same clipped two-layer stars the cards use — 4.5 is a real half
   star. */
.tw .tw-rate {
    min-width: 0;
    margin: 0 0 12px;
    padding: 0;
    border: 0;
}

/* Bootstrap's reboot floats legends and sizes them like headings. */
.tw .tw-rate > .tw-rate__legend {
    float: none;
    width: auto;
    padding: 0;
    line-height: inherit;
}

.tw .tw-rate__options {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 8px;
}

.tw .tw-rate__option {
    position: relative;
    display: block;
    margin: 0;
    cursor: pointer;
}

.tw .tw-rate__option input {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: 0;
    padding: 0;
    opacity: 0;
    pointer-events: none;
}

.tw .tw-rate__body {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 12px 6px 10px;
    border-radius: 14px;
    border: 1px solid var(--tw-line);
    background: var(--tw-inset);
    text-align: center;
    transition: border-color .2s ease, background-color .2s ease, box-shadow .2s ease;
}

.tw .tw-rate__option:hover .tw-rate__body { border-color: var(--tw-line-strong); }

.tw .tw-rate__value {
    font-size: 19px;
    font-weight: 900;
    line-height: 1;
    color: var(--tw-text);
}

.tw .tw-rate__caption {
    font-size: 11px;
    font-weight: 700;
    line-height: 1.3;
    color: var(--tw-muted);
}

/* Selected: gold outline + wash, a check disc in the corner (so the state is
   not carried by colour alone), and the numeral picks up the star colour. */
.tw .tw-rate__body::after {
    content: "";
    position: absolute;
    top: 6px;
    inset-inline-end: 6px;
    width: 15px;
    height: 15px;
    border-radius: 50%;
    background: var(--tw-gold) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.6 6.3l2.2 2.2 4.6-4.9' fill='none' stroke='%23241600' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 10px no-repeat;
    opacity: 0;
    transform: scale(.5);
    transition: opacity .2s ease, transform .25s cubic-bezier(.22, 1, .36, 1);
}

/* Dark: a glow from the top edge — a flat gold wash over navy mixes to a
   muddy olive. Light: a plain pale-gold fill reads clean on white. */
.tw .tw-rate__option input:checked + .tw-rate__body {
    border-color: color-mix(in srgb, var(--tw-gold) 62%, transparent);
    background:
        radial-gradient(120% 100% at 50% 0%, rgba(255, 184, 0, .18), rgba(255, 184, 0, 0) 72%),
        var(--tw-inset);
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--tw-gold) 30%, transparent);
}

html:not(.dark) .tw .tw-rate__option input:checked + .tw-rate__body {
    background: color-mix(in srgb, var(--tw-gold) 12%, #FFFFFF);
}

.tw .tw-rate__option input:checked + .tw-rate__body::after {
    opacity: 1;
    transform: none;
}

.tw .tw-rate__option input:checked + .tw-rate__body .tw-rate__value { color: var(--tw-amber-text); }
.tw .tw-rate__option input:checked + .tw-rate__body .tw-rate__caption { color: var(--tw-text-2); }

.tw .tw-rate__option input:focus-visible + .tw-rate__body {
    outline: 2px solid var(--tw-primary-2);
    outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
    .tw .tw-rate__body,
    .tw .tw-rate__body::after { transition: none; }
}

.tw .comment-form-note {
    display: flex;
    align-items: flex-start;
    gap: 7px;
    margin: 4px 0 14px;
    font-size: 11.5px;
    line-height: 1.9;
    color: var(--tw-muted);
}

.tw .comment-form-note i { font-size: 15px; flex: 0 0 auto; margin-top: 2px; }

.tw .comment-submit {
    width: 100%;
    height: 48px;
    border-radius: 14px;
    border: 0;
    background: var(--tw-grad);
    color: #fff;
    font-size: 14.5px;
    font-weight: 800;
    cursor: pointer;
    box-shadow: 0 12px 34px -14px rgba(0, 123, 255, .9);
}

.tw .comment-submit[disabled] { opacity: .6; cursor: default; }

.tw .comment-form-message {
    margin: 10px 0 0;
    font-size: 12.5px;
    font-weight: 700;
    line-height: 1.9;
}

.tw .comment-form-message.is-success { color: var(--tw-success); }
.tw .comment-form-message.is-error { color: var(--tw-error); }

/* =============================================================================
   Commenter profile modal
   -----------------------------------------------------------------------------
   Rendered outside the section wrapper, so it carries its own copy of the
   palette rather than inheriting the .tw custom properties.
   ========================================================================== */

.comment-profile-modal {
    position: fixed;
    inset: 0;
    z-index: 1080;
    display: grid;
    place-items: center;
    padding: 20px;
}

.comment-profile-modal[hidden] { display: none; }

.comment-profile-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(2, 9, 21, .72);
    backdrop-filter: blur(6px);
}

.comment-profile-dialog {
    position: relative;
    width: min(420px, 100%);
    max-height: 88vh;
    overflow-y: auto;
    padding: 28px 24px 24px;
    border-radius: 24px;
    border: 1px solid rgba(141, 196, 255, .3);
    background: #0A1A2F;
    box-shadow: 0 40px 90px -40px rgba(0, 0, 0, .9);
    color: #EAF2FF;
    text-align: center;
    animation: tw-pop .25s cubic-bezier(.22, 1, .36, 1);
}

html:not(.dark) .comment-profile-dialog {
    background: #FFFFFF;
    border-color: rgba(0, 72, 153, .18);
    color: #0A1A30;
}

@keyframes tw-pop {
    from { opacity: 0; transform: translateY(14px) scale(.97); }
    to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
    .comment-profile-dialog { animation: none; }
}

.comment-profile-close {
    position: absolute;
    top: 12px;
    inset-inline-end: 14px;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    border: 1px solid rgba(141, 196, 255, .25);
    background: rgba(255, 255, 255, .05);
    color: inherit;
    font-size: 20px;
    line-height: 1;
    cursor: pointer;
}

.comment-profile-close:hover { border-color: #1C8AFF; }

.comment-profile-avatar {
    width: 88px;
    height: 88px;
    border-radius: 50%;
    object-fit: cover;
    border: 2px solid #1C8AFF;
    box-shadow: 0 12px 34px -14px rgba(0, 123, 255, .9);
}

.comment-profile-name {
    margin: 14px 0 2px;
    font-size: 19px;
    font-weight: 900;
}

.comment-profile-role {
    margin: 0;
    font-size: 13px;
    font-weight: 600;
    color: #8FA5C2;
}

.comment-profile-stats {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1px;
    margin: 20px 0;
    border-radius: 16px;
    border: 1px solid rgba(141, 196, 255, .16);
    background: rgba(141, 196, 255, .16);
    overflow: hidden;
}

html:not(.dark) .comment-profile-stats {
    border-color: rgba(0, 72, 153, .12);
    background: rgba(0, 72, 153, .12);
}

.comment-profile-stats > div {
    padding: 14px 8px;
    background: #0A1A2F;
}

html:not(.dark) .comment-profile-stats > div { background: #fff; }

.comment-profile-stats b {
    display: block;
    font-family: dana, yekanbakh, sans-serif;
    font-size: 19px;
    font-weight: 900;
    color: #1C8AFF;
}

.comment-profile-stats span {
    display: block;
    margin-top: 3px;
    font-size: 11px;
    font-weight: 600;
    color: #8FA5C2;
}

.comment-profile-meta {
    margin: 0;
    display: grid;
    gap: 8px;
    text-align: start;
}

.comment-profile-meta > div {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 9px 12px;
    border-radius: 12px;
    background: rgba(255, 255, 255, .04);
    font-size: 12.5px;
}

html:not(.dark) .comment-profile-meta > div { background: rgba(10, 40, 80, .04); }

.comment-profile-meta dt { margin: 0; font-weight: 600; color: #8FA5C2; }
.comment-profile-meta dd { margin: 0; font-weight: 800; }

.comment-profile-quote {
    margin: 18px 0 0;
    padding: 14px 16px;
    border-radius: 14px;
    border-inline-start: 3px solid #1C8AFF;
    background: rgba(0, 123, 255, .09);
    text-align: start;
    font-size: 13px;
    line-height: 2.1;
    color: #C3D4EA;
}

html:not(.dark) .comment-profile-quote { color: #2B4463; }
