/* ==========================================================================
   Opportunities v2 - UI improvements pass

   Loaded only by front/opportunities/v2.blade.php, which is selected by
   OpportunityController::OPPORTUNITY_V2. The old page keeps its markup and
   none of these rules, so setting that flag to false reverts the page cleanly.

   Everything is scoped under .opp-v2 (or .opp-sprite), and every class carries an
   opp- prefix, because this page renders inside both shells: user/layouts/app for a
   member and front/layouts/app for a guest. css/custom.css already owns .risk-badge,
   .progress and .btn, so nothing here may be named after them.

   Palette, radii and card treatment are the same as css/documents/v2.css,
   css/account/v2.css and css/beneficiary/v2.css so the pages read as one product.
   ========================================================================== */

.opp-v2 {
    --opp-line: #e6e8ec;
    --opp-line-soft: #f0f1f4;
    --opp-muted: #6b7280;
    --opp-faint: #9aa1ad;
    --opp-ink: #1a1a1a;
    --opp-ink-2: #3f4550;
    --opp-brand: #ffcc2a;
    --opp-brand-dark: #e6b415;
    --opp-green: #0f7b52;
    --opp-green-bg: #e7f5ef;
    --opp-amber: #a2620a;
    --opp-amber-bg: #fdf3e2;
    --opp-red: #b42318;
    --opp-red-bg: #fdeceb;
    --opp-blue: #1c4f9c;
    --opp-blue-bg: #eaf0fb;
    --opp-radius: 10px;
    --opp-shadow: 0 1px 2px rgba(16, 24, 40, .05), 0 1px 3px rgba(16, 24, 40, .06);
    --opp-shadow-lg: 0 4px 12px rgba(16, 24, 40, .07);

    color: var(--opp-ink);
    font-size: 14px;
    line-height: 1.5;
}

/* On the public shell the navbar is .nav-top-fixed - absolutely positioned and 138px tall -
   so the page has to start below it. The old page cleared it with four <br>s. */
.opp-page-public {
    padding-top: 154px !important;
}

/* the icon sprite is inline in the page and must never take up space */
.opp-sprite {
    position: absolute;
    width: 0;
    height: 0;
    overflow: hidden;
}

.opp-v2 .d-none {
    display: none !important;
}

.opp-v2 .opp-num {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum";
}

.opp-v2 .opp-sr {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

/* --------------------------------------------------------------------------
   Buttons - .opp-btn rather than .btn, which css/custom.css already styles
   -------------------------------------------------------------------------- */
.opp-v2 .opp-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    padding: 9px 16px;
    border: 1px solid transparent;
    border-radius: 8px;
    box-shadow: none;
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    line-height: 1.4;
    white-space: nowrap;
    text-decoration: none;
    transition: background .12s ease, border-color .12s ease;
}

.opp-v2 .opp-btn:hover,
.opp-v2 .opp-btn:focus {
    text-decoration: none;
}

.opp-v2 .opp-btn-primary {
    background: var(--opp-brand);
    border-color: var(--opp-brand-dark);
    color: var(--opp-ink);
}

.opp-v2 .opp-btn-primary:hover {
    background: var(--opp-brand-dark);
    color: var(--opp-ink);
}

.opp-v2 .opp-btn-ghost {
    background: #fff;
    border-color: var(--opp-line);
    color: var(--opp-ink);
}

.opp-v2 .opp-btn-ghost:hover {
    background: #f4f5f7;
    color: var(--opp-ink);
}

.opp-v2 .opp-btn-sm {
    padding: 6px 11px;
    font-size: 12px;
}

.opp-v2 .opp-btn-block {
    width: 100%;
}

.opp-v2 .opp-btn:disabled {
    opacity: .5;
    cursor: not-allowed;
}

/* without this an icon inside a button takes its intrinsic size, which for these
   24-unit symbols is the whole button */
.opp-v2 .opp-btn svg {
    width: 15px;
    height: 15px;
    flex: none;
}

/* --------------------------------------------------------------------------
   Section counts and quiet links
   -------------------------------------------------------------------------- */
.opp-v2 .opp-pill {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 9px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 700;
    white-space: nowrap;
}

.opp-v2 .opp-pill::before {
    content: "";
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: currentColor;
}

.opp-v2 .opp-pill-ok { background: var(--opp-green-bg); color: var(--opp-green); }
.opp-v2 .opp-pill-info { background: var(--opp-blue-bg); color: var(--opp-blue); }
.opp-v2 .opp-pill-neutral { background: var(--opp-line-soft); color: var(--opp-ink-2); }

.opp-v2 .opp-lnk {
    color: var(--opp-blue);
    font-weight: 600;
    text-decoration: none;
}

.opp-v2 .opp-lnk:hover {
    text-decoration: underline;
}

/* --------------------------------------------------------------------------
   Guest notice - once at the top, not repeated under every card
   -------------------------------------------------------------------------- */
.opp-v2 .opp-notice {
    display: none;
    align-items: flex-start;
    gap: 11px;
    padding: 12px 14px;
    margin-bottom: 16px;
    background: var(--opp-blue-bg);
    border: 1px solid #cfdcf3;
    border-radius: var(--opp-radius);
}

.opp-v2.opp-as-guest .opp-notice {
    display: flex;
}

.opp-v2 .opp-notice-ic {
    display: grid;
    place-items: center;
    flex: none;
    width: 28px;
    height: 28px;
    border-radius: 8px;
    background: #fff;
    color: var(--opp-blue);
}

.opp-v2 .opp-notice-ic svg {
    width: 14px;
    height: 14px;
}

.opp-v2 .opp-notice p {
    margin: 0;
    font-size: 12.5px;
    line-height: 1.55;
    color: #24406e;
}

.opp-v2 .opp-notice b {
    color: #16304f;
}

/* --------------------------------------------------------------------------
   Sections

   The three headings are the page. There is no page title above them competing
   for the same job - the old page had three peer <h1>s and so does this.
   -------------------------------------------------------------------------- */
.opp-v2 .opp-sec {
    margin-bottom: 34px;
}

.opp-v2 .opp-sec-hd {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 12px;
}

.opp-v2 .opp-sec-title {
    margin: 0;
    font-size: 20px;
    font-weight: 700;
    letter-spacing: -.015em;
    color: var(--opp-ink);
}

/* its own line under the heading. It sat in the header row before, where margin-left: auto
   pushed it to the far right of the page, away from the title it qualifies. */
.opp-v2 .opp-sec-note {
    margin: -6px 0 12px;
    font-size: 12px;
    color: var(--opp-muted);
}

/* --------------------------------------------------------------------------
   Category filter - the old page's pills, as chips that carry their count
   -------------------------------------------------------------------------- */
.opp-v2 .opp-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 7px;
    margin-bottom: 14px;
}

.opp-v2 .opp-chip {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 6px 13px;
    background: #fff;
    border: 1px solid var(--opp-line);
    border-radius: 999px;
    color: var(--opp-ink-2);
    font-family: inherit;
    font-size: 12.5px;
    font-weight: 600;
    line-height: 1.4;
    transition: border-color .12s ease, background .12s ease;
}

.opp-v2 .opp-chip:hover:not(:disabled) {
    border-color: #d0d4db;
    background: #fbfbfc;
}

.opp-v2 .opp-chip i {
    padding: 1px 6px;
    background: var(--opp-line-soft);
    border-radius: 999px;
    color: var(--opp-faint);
    font-style: normal;
    font-size: 10.5px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* a chip whose count has not come back yet shows no badge at all */
.opp-v2 .opp-chip i:empty {
    display: none;
}

.opp-v2 .opp-chip[aria-pressed="true"] {
    background: var(--opp-ink);
    border-color: var(--opp-ink);
    color: #fff;
}

.opp-v2 .opp-chip[aria-pressed="true"] i {
    background: rgba(255, 255, 255, .18);
    color: var(--opp-brand);
}

/* the hover above is a pseudo-class more specific than the selected rule, so it was
   painting the chosen chip near-white while its own colour: #fff stayed - white on
   white. The chosen chip lifts instead of going pale. */
.opp-v2 .opp-chip[aria-pressed="true"]:hover:not(:disabled) {
    background: var(--opp-ink-2);
    border-color: var(--opp-ink-2);
    color: #fff;
}

/* a category with nothing in it stays visible but cannot be chosen - the old
   page offered every category everywhere, including on empty sections */
.opp-v2 .opp-chip:disabled {
    opacity: .45;
    cursor: not-allowed;
}

/* the two round arrows either side of the category strip. They are display: none until
   the narrow layout, where the strip is the thing that scrolls - see the max-width: 640px
   block, which is also where the wrapper becomes the row that puts them at its ends. */
.opp-v2 .opp-catnav {
    display: none;
    flex: none;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    padding: 0;
    border: 1px solid var(--opp-line);
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 3px rgba(16, 24, 40, .12);
    color: var(--opp-ink-2);
    transition: background .12s ease;
}

.opp-v2 .opp-catnav:hover {
    background: #f4f5f7;
}

.opp-v2 .opp-catnav i {
    font-size: 12px;
    line-height: 1;
}

/* in front of the strip, although it comes after it in the markup */
.opp-v2 .opp-catnav-prev {
    order: -1;
}

/* at that end of the strip there is nothing to scroll to. visibility rather than display,
   so the row does not jump sideways as the first arrow comes and goes. */
.opp-v2 .opp-catnav.is-off {
    visibility: hidden;
}

/* --------------------------------------------------------------------------
   Grid and footer
   -------------------------------------------------------------------------- */
.opp-v2 .opp-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 16px;
    align-items: stretch;
}

.opp-v2 .opp-grid.is-empty {
    display: block;
}

/* while the first page of a category is in flight. a spinner rather than a skeleton
   card: three sections load at once and three sets of ghost cards read as content */
.opp-v2 .opp-grid.is-loading::before {
    content: "";
    grid-column: 1 / -1;
    justify-self: center;
    width: 22px;
    height: 22px;
    margin: 26px 0;
    border: 2px solid var(--opp-line);
    border-top-color: var(--opp-faint);
    border-radius: 50%;
    animation: opp-spin .7s linear infinite;
}

@keyframes opp-spin {
    to { transform: rotate(360deg); }
}

/* count on the left, View More on the right - the same footer the redesigned
   Wallet and Beneficiary tables use, so the panel has one pagination pattern */
.opp-v2 .opp-foot {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 14px;
}

.opp-v2 .opp-count {
    font-size: 12px;
    font-weight: 600;
    color: var(--opp-muted);
}

.opp-v2 .opp-more {
    margin-left: auto;
}

/* --------------------------------------------------------------------------
   Card
   -------------------------------------------------------------------------- */
.opp-v2 .opp-card {
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: #fff;
    border: 1px solid var(--opp-line);
    border-radius: var(--opp-radius);
    box-shadow: var(--opp-shadow);
    transition: box-shadow .14s ease, border-color .14s ease;
}

.opp-v2 .opp-card:hover {
    border-color: #d8dbe1;
    box-shadow: var(--opp-shadow-lg);
}

.opp-v2 .opp-media {
    position: relative;
    overflow: hidden;
    aspect-ratio: 16 / 9;
    background: var(--opp-line-soft);
}

/* Taken out of the flow rather than sized at height:100%. The media box gets its height
   from aspect-ratio, which leaves that percentage unresolvable, so the image falls back
   to its own proportions and - being a flex item with min-height:auto - drags the box
   with it, giving every card a cover of a different height. */
.opp-v2 .opp-media img {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: block;
    object-fit: cover;
}

.opp-v2 .opp-tag {
    position: absolute;
    left: 10px;
    top: 10px;
    padding: 3px 9px;
    background: rgba(26, 26, 26, .82);
    border-radius: 999px;
    color: #fff;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .03em;
}

.opp-v2 .opp-stage {
    position: absolute;
    right: 10px;
    top: 10px;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 9px;
    background: var(--opp-brand);
    border-radius: 999px;
    color: var(--opp-ink);
    font-size: 10.5px;
    font-weight: 700;
}

.opp-v2 .opp-stage svg {
    width: 11px;
    height: 11px;
}

.opp-v2 .opp-body {
    display: flex;
    flex-direction: column;
    flex: 1;
    padding: 14px 15px 4px;
}

.opp-v2 .opp-card.is-study .opp-body {
    padding-bottom: 15px;
}

.opp-v2 .opp-head {
    display: flex;
    align-items: flex-start;
    gap: 8px;
}

.opp-v2 .opp-body h3 {
    flex: 1;
    min-width: 0;
    margin: 0;
    font-size: 14.5px;
    font-weight: 700;
    line-height: 1.3;
    letter-spacing: -.01em;
    color: var(--opp-ink);
}

.opp-v2 .opp-loc {
    margin: 3px 0 0;
    font-size: 12px;
    color: var(--opp-muted);
}

.opp-v2 .opp-study-note {
    margin: 11px 0 0;
    font-size: 12px;
    line-height: 1.5;
    color: var(--opp-muted);
}

/* --------------------------------------------------------------------------
   Risk rating and the reason behind it

   The old card put the reason in a title attribute rendered by a Bootstrap
   tooltip. Here it is a real element, so it can carry a coloured heading and
   wrap - and the badge itself is the trigger, as a button, because hover does
   not exist on touch and focus is how the keyboard reaches it.
   -------------------------------------------------------------------------- */
.opp-v2 .opp-risk {
    position: relative;
    display: inline-flex;
    align-items: center;
    flex: none;
}

.opp-v2 .opp-risk-badge {
    padding: 2px 9px;
    background: #fff;
    border: 1px solid currentColor;
    border-radius: 999px;
    color: inherit;
    font-family: inherit;
    font-size: 10.5px;
    font-weight: 700;
    line-height: 1.55;
    white-space: nowrap;
}

.opp-v2 button.opp-risk-badge {
    cursor: help;
    transition: background .12s ease;
}

.opp-v2 .opp-risk-low { color: var(--opp-green); }
.opp-v2 .opp-risk-med { color: #c2680c; }
.opp-v2 .opp-risk-high { color: var(--opp-red); }

.opp-v2 .opp-risk-low button.opp-risk-badge:hover { background: var(--opp-green-bg); }
.opp-v2 .opp-risk-med button.opp-risk-badge:hover { background: var(--opp-amber-bg); }
.opp-v2 .opp-risk-high button.opp-risk-badge:hover { background: var(--opp-red-bg); }

.opp-v2 .opp-risk-tip {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 60;
    width: 250px;
    padding: 10px 12px;
    background: var(--opp-ink);
    border-radius: 8px;
    box-shadow: 0 6px 20px rgba(0, 0, 0, .22);
    color: #e9eaec;
    font-size: 11.5px;
    font-weight: 500;
    line-height: 1.5;
    text-align: left;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity .12s ease;
}

.opp-v2 .opp-risk-tip b {
    display: block;
    margin-bottom: 4px;
    font-size: 12px;
    color: currentColor;
}

.opp-v2 .opp-risk-low .opp-risk-tip b { color: #5fd6a4; }
.opp-v2 .opp-risk-med .opp-risk-tip b { color: #ffb968; }
.opp-v2 .opp-risk-high .opp-risk-tip b { color: #ff9c92; }

/* hover for the mouse, focus for the keyboard and for a tap on touch */
.opp-v2 .opp-risk:hover .opp-risk-tip,
.opp-v2 .opp-risk-badge:focus + .opp-risk-tip {
    opacity: 1;
    visibility: visible;
}

/* --------------------------------------------------------------------------
   Funding

   Both figures labelled. The old card printed "$160 ( 0.06% )" beside
   "$250,000" with nothing saying which was which.
   -------------------------------------------------------------------------- */
.opp-v2 .opp-fund {
    margin-top: 13px;
}

.opp-v2 .opp-fund-top {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-bottom: 7px;
}

.opp-v2 .opp-fund-top .k {
    font-size: 11.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .045em;
    color: var(--opp-muted);
}

.opp-v2 .opp-fund-top b {
    margin-left: auto;
    font-size: 16px;
    font-weight: 700;
}

.opp-v2 .opp-prog-track {
    height: 8px;
    overflow: hidden;
    background: var(--opp-line-soft);
    border-radius: 5px;
}

.opp-v2 .opp-prog-fill {
    height: 100%;
    border-radius: 5px;
}

.opp-v2 .opp-prog-yellow { background: var(--opp-brand); }
.opp-v2 .opp-prog-grey { background: #a5a5a5; }

.opp-v2 .opp-fund-foot {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 7px;
    font-size: 11.5px;
    color: var(--opp-muted);
}

.opp-v2 .opp-investors {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    white-space: nowrap;
}

.opp-v2 .opp-investors svg {
    width: 12px;
    height: 12px;
}

/* --------------------------------------------------------------------------
   Yields - three equal columns, and the guest state swaps only the value
   -------------------------------------------------------------------------- */
.opp-v2 .opp-yields {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1px;
    overflow: hidden;
    margin-top: 14px;
    background: var(--opp-line-soft);
    border: 1px solid var(--opp-line-soft);
    border-radius: 9px;
}

.opp-v2 .opp-yield {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: 52px;
    padding: 9px 6px;
    background: #fff;
    text-align: center;
}

.opp-v2 .opp-yield b {
    display: block;
    font-size: 15px;
    font-weight: 700;
    letter-spacing: -.01em;
}

.opp-v2 .opp-yield span {
    margin-top: 2px;
    font-size: 10.5px;
    font-weight: 600;
    color: var(--opp-muted);
}

.opp-v2 .opp-yield.is-locked b {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    color: var(--opp-faint);
}

.opp-v2 .opp-lock {
    flex: none;
    width: 14px;
    height: 14px;
    vertical-align: middle;
}

/* a figure you can see is there but cannot read, as the old card's blurred % did */
.opp-v2 .opp-blur {
    font-style: normal;
    color: var(--opp-ink-2);
    filter: blur(4px);
    user-select: none;
    pointer-events: none;
}

/* --------------------------------------------------------------------------
   Countdown

   Kept, because investors use it. What changes is its weight: the old card gave
   it four large black boxes, louder than the yield and the Invest button.
   -------------------------------------------------------------------------- */
.opp-v2 .opp-clock {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 6px;
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid var(--opp-line-soft);
}

.opp-v2 .opp-clock span {
    padding: 5px 2px;
    background: var(--opp-line-soft);
    border-radius: 7px;
    text-align: center;
}

.opp-v2 .opp-clock b {
    display: block;
    font-size: 14px;
    font-weight: 700;
    line-height: 1.2;
    font-variant-numeric: tabular-nums;
    color: var(--opp-ink);
}

.opp-v2 .opp-clock i {
    display: block;
    margin-top: 1px;
    font-style: normal;
    font-size: 9px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--opp-muted);
}

/* only the last two days earn the alarm colour */
.opp-v2 .opp-clock.is-urgent span { background: var(--opp-amber-bg); }
.opp-v2 .opp-clock.is-urgent b { color: var(--opp-amber); }
.opp-v2 .opp-clock.is-urgent i { color: #8a5a10; }

.opp-v2 .opp-closed {
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid var(--opp-line-soft);
    font-size: 11.5px;
    color: var(--opp-muted);
}

.opp-v2 .opp-cta {
    padding: 12px 15px 15px;
}

.opp-v2 .opp-starts {
    margin: 0;
    padding: 9px 0;
    font-size: 12px;
    font-weight: 600;
    text-align: center;
    color: var(--opp-muted);
}

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

   Inline and small. The old page gave an empty section a 250px illustration and
   an <h2>, which made it louder than the sections that had something in them.
   -------------------------------------------------------------------------- */
.opp-v2 .opp-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: 26px 20px;
    background: #fbfbfc;
    border: 1px dashed var(--opp-line);
    border-radius: var(--opp-radius);
    text-align: center;
}

.opp-v2 .opp-empty-art {
    display: block;
    width: 150px;
    max-width: 60%;
    height: auto;
}

.opp-v2 .opp-empty h4 {
    margin: 0;
    font-size: 14px;
    font-weight: 700;
    color: var(--opp-ink);
}

/* --------------------------------------------------------------------------
   Platform statistics

   The old band was a full-width section with the footnote in small print
   beneath it; the footnote is the tooltip on the label it belongs to.
   -------------------------------------------------------------------------- */
.opp-v2 .opp-stats {
    margin-top: 8px;
    padding: 22px 20px;
    background: var(--opp-brand);
    border-radius: var(--opp-radius);
}

.opp-v2 .opp-stats-grid {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 18px;
}

.opp-v2 .opp-stat {
    text-align: center;
}

.opp-v2 .opp-stat b {
    display: block;
    font-size: 24px;
    font-weight: 800;
    letter-spacing: -.02em;
    color: var(--opp-ink);
}

/* the label and its tooltip dot stay on one centred line */
.opp-v2 .opp-stat span {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    margin-top: 4px;
    font-size: 12px;
    font-weight: 600;
    color: #5a4a08;
}

.opp-v2 .opp-hint {
    position: relative;
    display: inline-grid;
    place-items: center;
    flex: none;
    width: 14px;
    height: 14px;
    border: 1px solid #96811f;
    border-radius: 50%;
    color: #6b5a10;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0;
    text-transform: none;
    cursor: help;
}

.opp-v2 .opp-hint:hover,
.opp-v2 .opp-hint:focus {
    border-color: var(--opp-ink);
    color: var(--opp-ink);
    outline: none;
}

.opp-v2 .opp-hint::after {
    content: attr(data-tip);
    position: absolute;
    bottom: calc(100% + 8px);
    left: 50%;
    z-index: 60;
    width: 230px;
    padding: 8px 10px;
    transform: translateX(-50%);
    background: var(--opp-ink);
    border-radius: 7px;
    box-shadow: 0 4px 14px rgba(0, 0, 0, .16);
    color: #fff;
    font-size: 11.5px;
    font-weight: 500;
    line-height: 1.45;
    letter-spacing: 0;
    text-align: left;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity .12s ease;
}

.opp-v2 .opp-hint:hover::after,
.opp-v2 .opp-hint:focus::after {
    opacity: 1;
    visibility: visible;
}

/* ==========================================================================
   OPPORTUNITY DETAIL

   Loaded by front/opportunities/detail_v2.blade.php, which shares this file with the
   list: the risk badge, the funding bar, the yields and the counter above are the same
   parts, so the page behind a card reads as the same product. Everything below is what
   the detail page adds, scoped under .oppd-v2.
   ========================================================================== */
.opp-v2 .oppd-back {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin-bottom: 14px;
    color: var(--opp-muted);
    font-size: 12.5px;
    font-weight: 600;
    text-decoration: none;
}

.opp-v2 .oppd-back:hover {
    color: var(--opp-ink);
    text-decoration: none;
}

.opp-v2 .oppd-back svg {
    width: 14px;
    height: 14px;
}

.opp-v2 .oppd-head {
    margin-bottom: 18px;
}

.opp-v2 .oppd-title {
    margin: 0;
    font-size: 22px;
    font-weight: 700;
    letter-spacing: -.015em;
    color: var(--opp-ink);
}

.opp-v2 .oppd-sub {
    margin: 4px 0 0;
    font-size: 13px;
    color: var(--opp-muted);
}

.opp-v2 .oppd-push {
    margin-left: auto;
}

/* --------------------------------------------------------------------------
   Shell - content beside a rail that stays put

   The old invest panel sat at the top of a column that ended with the cover image,
   so it was off screen for the whole of the page it was asking the reader to act on.
   -------------------------------------------------------------------------- */
.opp-v2 .oppd-shell {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 340px;
    gap: 16px;
    align-items: start;
}

.opp-v2 .oppd-main {
    display: flex;
    flex-direction: column;
    gap: 16px;
    min-width: 0;
}

.opp-v2 .oppd-rail {
    position: sticky;
    top: 72px;
}

/* --------------------------------------------------------------------------
   Card frame, shared by the risk block, the tabs and the panel
   -------------------------------------------------------------------------- */
.opp-v2 .oppd-card {
    background: #fff;
    border: 1px solid var(--opp-line);
    border-radius: var(--opp-radius);
    box-shadow: var(--opp-shadow);
}

.opp-v2 .oppd-card-hd {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    padding: 14px 16px;
    border-bottom: 1px solid var(--opp-line-soft);
}

.opp-v2 .oppd-card-hd h3 {
    margin: 0;
    font-size: 14px;
    font-weight: 700;
    color: var(--opp-ink);
}

.opp-v2 .oppd-card-bd {
    padding: 16px;
}

/* the tabs sit flush in their header */
.opp-v2 .oppd-card-hd-tabs {
    padding: 0 6px;
}

.opp-v2 .oppd-hero {
    position: relative;
    overflow: hidden;
    aspect-ratio: 16 / 7;
    background: var(--opp-line-soft);
    border: 1px solid var(--opp-line);
    border-radius: var(--opp-radius);
}

/* the link is the layer, not the image. css/custom.css positions anchors, which makes the
   <a> the containing block for anything absolute inside it - and it has no height of its own,
   so an image at height:100% came out at nothing. */
.opp-v2 .oppd-hero > a {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: block;
}

.opp-v2 .oppd-hero img {
    width: 100%;
    height: 100%;
    display: block;
    object-fit: cover;
}

/* the placeholder is a small graphic, so it is centred rather than stretched */
.opp-v2 .oppd-hero-fallback {
    object-fit: contain;
    padding: 24px;
    opacity: .55;
}

/* the old risk description was two sentences in a 60px box with its own scrollbar */
.opp-v2 .oppd-risk-why {
    margin: 0;
    font-size: 12.5px;
    line-height: 1.6;
    color: var(--opp-ink-2);
}

/* --------------------------------------------------------------------------
   Tabs
   -------------------------------------------------------------------------- */
.opp-v2 .oppd-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 2px;
}

.opp-v2 .oppd-tab {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 14px 12px;
    background: none;
    border: 0;
    border-bottom: 2px solid transparent;
    color: var(--opp-muted);
    font-family: inherit;
    font-size: 12.5px;
    font-weight: 600;
    white-space: nowrap;
}

.opp-v2 .oppd-tab:hover {
    color: var(--opp-ink);
}

.opp-v2 .oppd-tab[aria-selected="true"] {
    border-bottom-color: var(--opp-brand);
    color: var(--opp-ink);
}

.opp-v2 .oppd-tab-n {
    padding: 1px 6px;
    background: var(--opp-line-soft);
    border-radius: 999px;
    color: var(--opp-ink-2);
    font-size: 10.5px;
    font-weight: 700;
}

.opp-v2 .oppd-pane {
    min-width: 0;
}

/* --------------------------------------------------------------------------
   Details

   The old page printed these as "Label: value" paragraphs under a heading that
   repeated the property name, which by then had already been printed twice.
   -------------------------------------------------------------------------- */
.opp-v2 .oppd-facts {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1px;
    overflow: hidden;
    margin: 0 0 18px;
    background: var(--opp-line-soft);
    border: 1px solid var(--opp-line-soft);
    border-radius: 9px;
}

.opp-v2 .oppd-facts > div {
    padding: 11px 13px;
    background: #fff;
}

.opp-v2 .oppd-facts dt {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .045em;
    color: var(--opp-muted);
}

.opp-v2 .oppd-facts dd {
    margin: 4px 0 0;
    font-size: 12.5px;
    font-weight: 600;
}

/* the description, the improvements, the finance note and the legal terms are all
   CMS html, so this styles whatever tags come back rather than a fixed shape */
/* No measure cap. A line length limit reads better on its own, but everything else in
   this card - the facts row, the specs, the gallery - runs the full width, so capping
   only the prose left a ragged gutter down the right of the card instead. */
.opp-v2 .oppd-prose {
    font-size: 13px;
    line-height: 1.65;
    color: var(--opp-ink-2);
}

.opp-v2 .oppd-prose p {
    margin: 0 0 10px;
}

.opp-v2 .oppd-prose p:last-child {
    margin-bottom: 0;
}

.opp-v2 .oppd-prose b,
.opp-v2 .oppd-prose strong {
    color: var(--opp-ink);
}

.opp-v2 .oppd-prose ul,
.opp-v2 .oppd-prose ol {
    margin: 8px 0 10px;
    padding-left: 18px;
}

.opp-v2 .oppd-prose li {
    margin-bottom: 6px;
}

.opp-v2 .oppd-prose img {
    max-width: 100%;
    height: auto;
}

.opp-v2 .oppd-prose table {
    width: 100%;
    margin: 10px 0;
    border-collapse: collapse;
}

.opp-v2 .oppd-prose th,
.opp-v2 .oppd-prose td {
    padding: 8px 10px;
    border: 1px solid var(--opp-line);
    text-align: left;
}

.opp-v2 .oppd-h {
    margin: 24px 0 12px;
    font-size: 14px;
    font-weight: 700;
    color: var(--opp-ink);
}

.opp-v2 .oppd-empty {
    margin: 0;
    font-size: 13px;
    color: var(--opp-muted);
}

/* the four figures the old page put in a row of icons above the gallery */
.opp-v2 .oppd-specs {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 12px;
    margin-top: 18px;
    padding: 14px 0;
    border-top: 1px solid var(--opp-line-soft);
    border-bottom: 1px solid var(--opp-line-soft);
}

.opp-v2 .oppd-spec {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
}

.opp-v2 .oppd-spec svg {
    width: 17px;
    height: 17px;
    margin-bottom: 4px;
    color: var(--opp-faint);
}

.opp-v2 .oppd-spec b {
    font-size: 14px;
    font-weight: 700;
}

.opp-v2 .oppd-spec span {
    font-size: 11px;
    color: var(--opp-muted);
}

/* the old gallery was a Flickity carousel with a second carousel of thumbnails
   under it, for four images */
.opp-v2 .oppd-gallery {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 10px;
}

.opp-v2 .oppd-shot {
    position: relative;
    display: block;
    overflow: hidden;
    aspect-ratio: 4 / 3;
    background: var(--opp-line-soft);
    border: 1px solid var(--opp-line);
    border-radius: 9px;
    cursor: zoom-in;
}

.opp-v2 .oppd-shot img {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: block;
    object-fit: cover;
}

.opp-v2 .oppd-shot.is-plan {
    aspect-ratio: 16 / 9;
    max-width: 420px;
}

.opp-v2 .oppd-map {
    overflow: hidden;
    border: 1px solid var(--opp-line);
    border-radius: 9px;
}

/* the google map the old page drew, which had no height of its own here */
.opp-v2 .oppd-map #map {
    height: 260px;
}

.opp-v2 .oppd-map-foot {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    padding: 10px 13px;
    border-top: 1px solid var(--opp-line);
    font-size: 12px;
    color: var(--opp-muted);
}

.opp-v2 .oppd-map-foot > span {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.opp-v2 .oppd-map-foot svg {
    width: 13px;
    height: 13px;
    color: var(--opp-faint);
}

/* reference text: kept, closed. The old page ended on it at full weight, under a
   heading the same size as Gallery. */
.opp-v2 .oppd-legal {
    margin-top: 24px;
    padding-top: 14px;
    border-top: 1px solid var(--opp-line-soft);
}

/* the marker goes to the right of the line rather than in front of the words: the
   native one is dropped, and ::after draws a caret that turns when the block opens */
.opp-v2 .oppd-legal summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    color: var(--opp-ink-2);
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
    list-style: none;
}

.opp-v2 .oppd-legal summary::-webkit-details-marker {
    display: none;
}

.opp-v2 .oppd-legal summary::after {
    content: "";
    flex: none;
    width: 7px;
    height: 7px;
    margin-right: 3px;
    border-right: 1.6px solid currentColor;
    border-bottom: 1.6px solid currentColor;
    transform: translateY(-2px) rotate(45deg);
    transition: transform .15s ease;
}

.opp-v2 .oppd-legal[open] summary::after {
    transform: translateY(1px) rotate(225deg);
}

.opp-v2 .oppd-legal summary:hover {
    color: var(--opp-ink);
}

.opp-v2 .oppd-legal .oppd-prose {
    margin-top: 10px;
    font-size: 12px;
    color: var(--opp-muted);
}

/* --------------------------------------------------------------------------
   The guest state

   A guest saw placeholder paragraphs behind a blur on the old page, which also
   opened the login prompt the moment the page loaded. Same arrangement, without
   the page of dummy prose behind it.
   -------------------------------------------------------------------------- */
.opp-v2 .oppd-locked-note {
    margin-bottom: 16px;
    padding: 12px 14px;
    background: var(--opp-blue-bg);
    border: 1px solid #cfdcf3;
    border-radius: var(--opp-radius);
    font-size: 12.5px;
    line-height: 1.55;
    color: #24406e;
}

.opp-v2 .oppd-blur {
    filter: blur(4px);
    pointer-events: none;
    user-select: none;
}

.opp-v2 .oppd-skel-lines {
    display: grid;
    gap: 9px;
    margin-bottom: 18px;
}

.opp-v2 .oppd-skel-lines span {
    height: 10px;
    background: var(--opp-line-soft);
    border-radius: 4px;
}

.opp-v2 .oppd-skel-lines span:nth-child(3) { width: 82%; }
.opp-v2 .oppd-skel-lines span:nth-child(6) { width: 64%; }

/* --------------------------------------------------------------------------
   Documents

   The old tab listed a filename and an arrow: nothing to say a row was a link.
   -------------------------------------------------------------------------- */
.opp-v2 .oppd-doc {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 11px 13px;
    background: #fff;
    border: 1px solid var(--opp-line);
    border-radius: 9px;
    cursor: pointer;
    transition: border-color .12s ease, box-shadow .14s ease;
}

.opp-v2 .oppd-doc + .oppd-doc {
    margin-top: 8px;
}

.opp-v2 .oppd-doc:hover {
    border-color: #d8dbe1;
    box-shadow: var(--opp-shadow-lg);
}

.opp-v2 .oppd-doc-ic {
    display: grid;
    place-items: center;
    flex: none;
    width: 32px;
    height: 32px;
    background: var(--opp-line-soft);
    border-radius: 8px;
    color: var(--opp-ink-2);
}

.opp-v2 .oppd-doc-ic svg {
    width: 15px;
    height: 15px;
}

.opp-v2 .oppd-doc-tx {
    flex: 1;
    min-width: 0;
}

.opp-v2 .oppd-doc-tx b {
    display: block;
    font-size: 13px;
    font-weight: 600;
}

.opp-v2 .oppd-doc-tx i {
    display: block;
    margin-top: 2px;
    font-style: normal;
    font-size: 11px;
    color: var(--opp-muted);
}

.opp-v2 .oppd-doc-go {
    flex: none;
    color: var(--opp-faint);
    font-size: 14px;
    font-style: normal;
}

/* --------------------------------------------------------------------------
   Timeline - a right-hand column on the old page, which left a strip of white
   running the length of the tabs whenever a project had one or two entries
   -------------------------------------------------------------------------- */
.opp-v2 .oppd-timeline {
    position: relative;
    list-style: none;
    margin: 0;
    padding: 0 0 0 22px;
}

.opp-v2 .oppd-timeline::before {
    content: "";
    position: absolute;
    left: 5px;
    top: 6px;
    bottom: 6px;
    width: 2px;
    background: var(--opp-line);
}

.opp-v2 .oppd-tl {
    position: relative;
    padding: 0 0 20px;
}

.opp-v2 .oppd-tl:last-child {
    padding-bottom: 0;
}

.opp-v2 .oppd-tl::before {
    content: "";
    position: absolute;
    left: -22px;
    top: 3px;
    width: 12px;
    height: 12px;
    background: #fff;
    border: 3px solid var(--opp-brand);
    border-radius: 50%;
}

.opp-v2 .oppd-tl-hd {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
}

.opp-v2 .oppd-tl-hd b {
    font-size: 13px;
    font-weight: 700;
}

.opp-v2 .oppd-tl-doc {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin-left: auto;
    color: var(--opp-blue);
    font-size: 11.5px;
    font-weight: 600;
    cursor: pointer;
}

.opp-v2 .oppd-tl-doc svg {
    width: 12px;
    height: 12px;
}

.opp-v2 .oppd-tl-date {
    display: block;
    margin-top: 4px;
    font-size: 11px;
    color: var(--opp-faint);
}

/* --------------------------------------------------------------------------
   The invest panel
   -------------------------------------------------------------------------- */
.opp-v2 .oppd-invest .oppd-card-bd {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.opp-v2 .oppd-fund-top {
    display: flex;
    align-items: baseline;
    gap: 7px;
    margin-bottom: 8px;
}

.opp-v2 .oppd-fund-top b {
    font-size: 20px;
    font-weight: 700;
    letter-spacing: -.02em;
}

.opp-v2 .oppd-fund-top span {
    font-size: 12px;
    color: var(--opp-muted);
}

.opp-v2 .oppd-fund-foot {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 8px;
    font-size: 11.5px;
    color: var(--opp-muted);
}

.opp-v2 .oppd-closes {
    padding-top: 12px;
    border-top: 1px solid var(--opp-line-soft);
}

.opp-v2 .oppd-closes .k {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 11.5px;
    font-weight: 600;
    color: var(--opp-muted);
}

.opp-v2 .oppd-closes .k svg {
    width: 13px;
    height: 13px;
    color: var(--opp-faint);
}

/* the counter is already inside a bordered block here */
.opp-v2 .oppd-closes .opp-clock {
    margin-top: 9px;
    padding-top: 0;
    border-top: 0;
}

.opp-v2 .oppd-invest .opp-yields {
    margin-top: 0;
}

/* the two states that replace the form */
.opp-v2 .oppd-state {
    padding: 11px 13px;
    background: var(--opp-red-bg);
    border-radius: 9px;
    color: var(--opp-red);
    font-size: 12.5px;
    font-weight: 600;
    text-align: center;
}

/* --------------------------------------------------------------------------
   Amount

   The field stays readonly and the slider stays noUiSlider, as on the old page -
   only the frame around them is new.
   -------------------------------------------------------------------------- */
.opp-v2 .oppd-amount > label {
    display: block;
    margin-bottom: 6px;
    color: var(--opp-ink-2);
    font-size: 11.5px;
    font-weight: 600;
}

.opp-v2 .oppd-amount-in {
    display: flex;
    align-items: stretch;
}

.opp-v2 .oppd-cur {
    display: grid;
    place-items: center;
    padding: 0 11px;
    background: var(--opp-line-soft);
    border: 1px solid var(--opp-line);
    border-right: 0;
    border-radius: 8px 0 0 8px;
    color: var(--opp-ink-2);
    font-size: 12px;
    font-weight: 700;
}

.opp-v2 .oppd-amount-in .form-control {
    flex: 1;
    min-width: 0;
    height: 38px;
    padding: 0 11px;
    background: #fff;
    border: 1px solid var(--opp-line);
    border-radius: 0 8px 8px 0;
    box-shadow: none;
    color: var(--opp-ink);
    font-size: 14px;
    font-weight: 600;
}

/* noUiSlider, as the old page set it up - the tweaks below were in that page's own
   <style> block, and without them the value tooltip sits over the amount field */
.opp-v2 .amount_slider-range {
    height: 6px;
    margin: 16px 8px 36px;
    background: var(--opp-line-soft);
    border: 0;
    border-radius: 4px;
    box-shadow: none;
}

.opp-v2 .amount_slider-range .noUi-connect {
    background: var(--opp-brand);
}

.opp-v2 .amount_slider-range .noUi-handle {
    top: -6px;
    right: -9px;
    width: 18px;
    height: 18px;
    border: 1px solid var(--opp-brand-dark);
    border-radius: 50%;
    background: var(--opp-brand);
    box-shadow: 0 1px 3px rgba(16, 24, 40, .2);
    cursor: pointer;
    pointer-events: auto !important;
}

.opp-v2 .amount_slider-range .noUi-handle::before,
.opp-v2 .amount_slider-range .noUi-handle::after {
    display: none;
}

.opp-v2 .amount_slider-range .noUi-tooltip {
    bottom: auto !important;
    top: 130%;
    padding: 1px 8px;
    background: var(--opp-ink);
    border: 0;
    border-radius: 999px;
    color: #fff;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .25px;
}

.opp-v2 .amount_slider-range[disabled] .noUi-handle {
    cursor: not-allowed;
    opacity: .6;
}

.opp-v2 .oppd-amount-foot {
    display: flex;
    gap: 8px;
    margin-top: 14px;
    font-size: 11px;
    color: var(--opp-faint);
}

.opp-v2 label#invest_amount-error.error {
    display: block;
    float: none;
    margin: 8px 0 0;
    color: #b42318;
    font-size: 11.5px;
    font-weight: 600;
}

/* Currently hidden - the class is on the block in detail_v2.blade.php, and taking it
   off there brings the estimate back. The block was not in the v5 design and costs the
   panel about 120px; the Simulate dialog works the same figures out. Kept rather than
   deleted because the markup and the script that fills it are already written. */
.opp-v2 .oppd-preview-off {
    display: none !important;
}

/* what the Simulate dialog works out, without opening it */
.opp-v2 .oppd-preview {
    display: grid;
    gap: 7px;
    margin-top: 14px;
    padding: 11px 13px;
    background: #fbfbfc;
    border: 1px solid var(--opp-line);
    border-radius: 9px;
}

.opp-v2 .oppd-preview > div {
    display: flex;
    align-items: baseline;
    gap: 10px;
    font-size: 12px;
    color: var(--opp-muted);
}

.opp-v2 .oppd-preview b {
    margin-left: auto;
    color: var(--opp-ink);
    font-size: 12.5px;
    font-weight: 600;
}

.opp-v2 .oppd-preview .is-total {
    padding-top: 7px;
    border-top: 1px solid var(--opp-line-soft);
    color: var(--opp-ink-2);
    font-weight: 600;
}

.opp-v2 .oppd-preview .is-total b {
    font-size: 14px;
}

.opp-v2 .oppd-invest .opp-btn-block {
    margin-top: 10px;
}

/* the old page wrapped this one date in a black panel with an illustration */
.opp-v2 .oppd-started {
    margin: 0;
    color: var(--opp-faint);
    font-size: 11px;
    line-height: 1.5;
    text-align: center;
}

/* --------------------------------------------------------------------------
   The Simulate Invest dialog.

   Nothing here restyles it - its design is the one that shipped. These are the
   rules the old detail page kept in its own <style> block, which sat outside the
   dialog and so never travelled with it. That page still carries them; the
   redesigned page does not, so the dialog arrived without them - the handle would
   not drag, the value bubble covered the field above it, and the US$ tag sat to
   the right of the amount instead of the left.

   The dialog prints outside .opp-v2 (see detail_v2.blade.php), so these are scoped
   to its own id. This stylesheet loads on the redesigned pages only.
   -------------------------------------------------------------------------- */

/* the same handle the detail page draws - custom.css gives this one a 24px circle with a
   white ring, sat off centre by noUiSlider's own right: -17px, and pointer-events: none
   !important, which makes it ignore the drag so only a click on the track moves the value.
   top is -5px, not the detail page's -6px: that track is 6px tall and this one is 8px. */
#investment-simulator-modal .noUi-horizontal .noUi-handle {
    top: -5px;
    right: -9px;
    width: 18px;
    height: 18px;
    border: 1px solid #e6b415;
    border-radius: 50%;
    background: #ffcc2a;
    box-shadow: 0 1px 3px rgba(16, 24, 40, .2);
    cursor: pointer;
    pointer-events: auto !important;
}

/* the bubble's default place is above the track, which is where the amount field is.
   Colours are literals: --opp-brand and the rest are declared on .opp-v2, and the dialog
   prints outside it. */
#investment-simulator-modal .noUi-horizontal .noUi-tooltip {
    bottom: auto !important;
    top: 130%;
    padding: 1px 8px;
    border: 0;
    border-radius: 999px;
    background: #1a1a1a;
    color: #fff;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.25px;
}

#investment-simulator-modal .want-invest-right .dollar-icon {
    right: auto;
    left: 0;
    width: 45px;
    border-radius: 5px 0 0 5px;
    font-size: 16px;
}

#investment-simulator-modal .want-invest-right input {
    padding-right: 10px;
    padding-left: 60px;
}

/* --------------------------------------------------------------------------
   The Simulate button asks for attention.

   The simulator's script adds .vibrate-btn to this button every time the pointer
   leaves it, which shakes it. That script is shared with the old page, so the shake
   is answered here rather than removed there: the button stays still and a band of
   brand yellow sweeps across it, right to left, with a pause between passes.
   -------------------------------------------------------------------------- */
.opp-v2 #show-investment-simulator-modal {
    position: relative;
    overflow: hidden;
}

.opp-v2 #show-investment-simulator-modal,
.opp-v2 #show-investment-simulator-modal.vibrate-btn {
    animation: none;
    transform: none;
}

.opp-v2 #show-investment-simulator-modal::after {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: 45%;
    background: linear-gradient(100deg, rgba(255, 204, 42, 0) 0%, rgba(255, 204, 42, 0.6) 50%, rgba(255, 204, 42, 0) 100%);
    transform: translateX(240%);
    pointer-events: none;
    animation: oppd-shine 3.2s ease-in-out infinite;
}

@keyframes oppd-shine {
    /* the sweep is the first fifth of the cycle; the rest is the wait before the next one */
    0% { transform: translateX(240%); }
    20% { transform: translateX(-120%); }
    100% { transform: translateX(-120%); }
}

/* a hint, not a distraction: it stops once the pointer is on the button */
.opp-v2 #show-investment-simulator-modal:hover::after {
    animation: none;
    opacity: 0;
}

@media (prefers-reduced-motion: reduce) {
    .opp-v2 #show-investment-simulator-modal::after {
        animation: none;
        opacity: 0;
    }
}

/* --------------------------------------------------------------------------
   Start New Simulation, as a menu.

   It used to be a full-width card that slid down between the property header and
   the results, pushing the very figures it was about to change off the screen. It
   is the same card, with the same ids and the same handlers - it is only printed
   as a floating menu under the button that opens it, so the results stay in view
   and visibly change when Generate Results is pressed.

   Every rule below hangs off .sim-menu, which opportunity_detail_v2.js puts on the
   dialog only while its SIMULATION_MENU flag is on - turn that off and the sliding
   card is back, with nothing here to undo. That script also places the menu under
   the button; these rules only give it its shape. The old detail page loads neither
   file, so it keeps the card it has always had either way.
   -------------------------------------------------------------------------- */
#investment-simulator-modal.sim-menu .modal-body > .container {
    position: relative;
}

#investment-simulator-modal.sim-menu #simulation-form {
    position: absolute;
    z-index: 20;
    width: 320px;
    /* a 320px menu would touch the edge of a small phone */
    max-width: calc(100vw - 30px);
    margin: 0;
    border: 0;
    border-radius: 10px;
    box-shadow: 0 12px 32px rgba(16, 24, 40, 0.18), 0 0 0 1px rgba(16, 24, 40, 0.06);
}

/* the notch that points back at the button. Left, on both widths: below 768px the
   button is left-aligned anyway, and above it the menu hangs from the button's
   left edge - which is what was asked for. */
#investment-simulator-modal.sim-menu #simulation-form::before {
    content: '';
    position: absolute;
    top: -5px;
    left: var(--sim-notch, 22px);
    width: 12px;
    height: 12px;
    border-radius: 2px;
    background: #fff;
    transform: rotate(45deg);
}

/* a menu is tighter than the card was. The utilities being overridden here carry
   Bootstrap's own !important, so these have to as well. */
#investment-simulator-modal.sim-menu #simulation-form > .d-flex {
    padding: 12px 16px 0 !important;
}

#investment-simulator-modal.sim-menu #simulation-form > .d-flex h5 {
    font-size: 15px;
}

#investment-simulator-modal.sim-menu #simulation-form > form {
    padding: 12px 16px 12px !important;
}

#investment-simulator-modal.sim-menu #simulation-form .form-group {
    margin-bottom: 8px;
}

#investment-simulator-modal.sim-menu #simulation-form label {
    margin-bottom: 4px;
}

/* one goal to a row. They are a col-md-6 each, which the viewport still calls
   medium however narrow the menu is, so side by side they were squeezed into
   half of 320px. The rules above give back the height this costs. */
#investment-simulator-modal.sim-menu #simulation-form .form-row > [class*="col-"] {
    flex: 0 0 100%;
    max-width: 100%;
}

/* room under the track for the slider's value bubble, which sits below it */
#investment-simulator-modal.sim-menu #simulation-form .form-group.pb-4 {
    padding-bottom: 24px !important;
}

#investment-simulator-modal.sim-menu #simulation-form .form-control {
    height: 36px;
    font-size: 14px;
}

#investment-simulator-modal.sim-menu #simulation-form .run-new-simulation {
    padding: 8px 18px !important;
    font-size: 14px;
}

/* --------------------------------------------------------------------------
   Responsive - last, so it wins over everything above
   -------------------------------------------------------------------------- */
@media (max-width: 1100px) {
    .opp-v2 .opp-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .opp-v2 .opp-stats-grid { grid-template-columns: repeat(3, 1fr); gap: 22px 18px; }
}

@media (max-width: 900px) {
    /* the rail stops being a rail and becomes the first thing on the page */
    .opp-v2 .oppd-shell { grid-template-columns: 1fr; }
    .opp-v2 .oppd-rail { position: static; order: -1; }
    .opp-v2 .oppd-specs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 640px) {
    /* one row that scrolls, rather than six pills of six different widths wrapping into
       four ragged rows. An arrow at each end of the row says so, and steps it. */
    .opp-v2 .opp-chips-wrap {
        display: flex;
        align-items: center;
        gap: 6px;
        margin-bottom: 14px;
    }

    .opp-v2 .opp-catnav {
        display: inline-flex;
    }

    /* min-width: 0 - a flex item will not shrink below its content otherwise, and the
       strip's content is all six chips, so the row would push the arrows off screen */
    .opp-v2 .opp-chips {
        flex: 1 1 auto;
        min-width: 0;
        flex-wrap: nowrap;
        overflow-x: auto;
        margin-bottom: 0;
        scroll-behavior: smooth;
        scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
    }

    /* the row is swiped, or stepped with the arrows - not dragged by a bar */
    .opp-v2 .opp-chips::-webkit-scrollbar {
        display: none;
    }

    /* a flex item shrinks to fit by default, which would squeeze "Land & Development"
       onto two lines rather than letting the row scroll */
    .opp-v2 .opp-chip {
        flex: none;
    }

    .opp-v2 .opp-grid { grid-template-columns: 1fr; }
    .opp-v2 .opp-stats-grid { grid-template-columns: repeat(2, 1fr); }
    .opp-v2 .opp-stat:last-child { grid-column: 1 / -1; }

    .opp-v2 .oppd-facts { grid-template-columns: 1fr; }
    .opp-v2 .oppd-gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); }

    /* hangs off the left of the dot rather than being centred on it. Centred, a 230px
       panel reaches past the right edge of a narrow screen - and because it is laid out
       even while hidden, that alone gives the whole page a horizontal scrollbar. */
    .opp-v2 .opp-hint::after {
        left: auto;
        right: 0;
        width: 200px;
        transform: none;
    }
}

/* --------------------------------------------------------------------------
   Document View dialog

   The viewer the Documents tab and the timeline open. It was a stock Bootstrap
   modal - square corners, a footer button that custom.css has since turned solid
   black - beside dialogs elsewhere on the panel that are not. These give it the
   shape the Documents and Account dialogs have, without pulling in their
   stylesheets: it prints outside .opp-v2, so everything is on its own id, and
   colours are literals because --opp-* are declared on .opp-v2.
   -------------------------------------------------------------------------- */
#document_view_modal .modal-content {
    border: 0;
    border-radius: 12px;
    box-shadow: 0 12px 34px rgba(16, 24, 40, .18);
    overflow: hidden;
}

#document_view_modal .modal-header {
    align-items: center;
    padding: 16px 18px;
    border-bottom: 1px solid #f0f1f4;
}

#document_view_modal .modal-title {
    margin: 0;
    color: #1a1a1a;
    font-size: 15px;
    font-weight: 700;
    line-height: 1.4;
}

#document_view_modal .close {
    margin: 0 0 0 auto;
    padding: 0 2px;
    border: 0;
    background: none;
    color: #9aa1ad;
    font-size: 24px;
    line-height: 1;
    opacity: 1;
    text-shadow: none;
}

#document_view_modal .close:hover {
    color: #1a1a1a;
    opacity: 1;
}

#document_view_modal .modal-body {
    padding: 16px 18px 18px;
}

/* follows the viewport instead of the old fixed 500px, so a page of the document is
   readable on a laptop without the dialog running off the bottom */
#document_view_modal .modal-body iframe {
    display: block;
    width: 100%;
    height: min(70vh, 640px);
    min-height: 320px;
    border: 1px solid #e6e8ec;
    border-radius: 8px;
    background: #f4f5f7;
}

#document_view_modal .modal-footer {
    justify-content: flex-end;
    padding: 13px 18px;
    border-top: 1px solid #f0f1f4;
    background: #fbfbfc;
}

#document_view_modal .oppd-dv-btn {
    min-width: 104px;
    padding: 7px 14px;
    border: 1px solid #e6e8ec;
    border-radius: 8px;
    background: #fff;
    color: #1a1a1a;
    font-size: 12.5px;
    font-weight: 600;
    line-height: 20px;
    transition: background .12s, border-color .12s;
}

#document_view_modal .oppd-dv-btn:hover {
    background: #f4f5f7;
    color: #1a1a1a;
}

/* --------------------------------------------------------------------------
   Home page featured opportunities (front/opportunities/home_featured_v2).
   The same card in the home page's owl carousel.
   -------------------------------------------------------------------------- */

/* every slide as tall as the tallest, so the Invest buttons line up */
.opp-v2.opp-home .owl-stage {
    display: flex;
}

.opp-v2.opp-home .owl-item {
    display: flex;
    padding: 12px 10px 16px;
}

.opp-v2.opp-home .opp-card {
    width: 100%;
}

.opp-v2.opp-home .opp-home-foot {
    margin-top: 18px;
    text-align: center;
}

/* above the section's building illustration, which hangs over the top of the section */
.opp-v2.opp-home {
    position: relative;
    z-index: 1;
}

/* The arrows: custom.css draws them as black squares flipped with a matrix. Here they are
   round and light like the cards, centred on the slide, with the same yellow on hover.
   The carousel keeps a lane each side for them, so they never sit on a card. */
.opp-v2.opp-home .realestate-main {
    padding: 0 44px;
}

.opp-v2.opp-home .realestate-main .owl-nav .owl-prev,
.opp-v2.opp-home .realestate-main .owl-nav .owl-next {
    top: 50%;
    width: 42px;
    height: 42px;
    margin: 0;
    background: #fff;
    border: 1px solid var(--opp-line);
    border-radius: 50%;
    box-shadow: 0 6px 16px rgba(16, 24, 40, .12);
    color: var(--opp-ink);
    font-size: 22px;
    line-height: 1;
    transform: translateY(-50%);
    transition: background .14s ease, border-color .14s ease, box-shadow .14s ease;
}

.opp-v2.opp-home .realestate-main .owl-nav .owl-prev {
    left: 0;
}

.opp-v2.opp-home .realestate-main .owl-nav .owl-next {
    right: 0;
}

.opp-v2.opp-home .realestate-main .owl-nav .owl-prev i,
.opp-v2.opp-home .realestate-main .owl-nav .owl-next i {
    transform: none;
}

.opp-v2.opp-home .realestate-main .owl-nav .owl-prev i {
    margin-right: 2px;
}

.opp-v2.opp-home .realestate-main .owl-nav .owl-next i {
    margin-left: 2px;
}

.opp-v2.opp-home .realestate-main .owl-nav .owl-prev:hover,
.opp-v2.opp-home .realestate-main .owl-nav .owl-next:hover {
    background: var(--opp-brand);
    border-color: var(--opp-brand);
    box-shadow: 0 8px 20px rgba(16, 24, 40, .16);
    color: var(--opp-ink);
}

.opp-v2.opp-home .realestate-main .owl-nav .owl-prev:focus,
.opp-v2.opp-home .realestate-main .owl-nav .owl-next:focus {
    outline: none;
}

.opp-v2.opp-home .realestate-main .owl-nav .owl-prev:focus-visible,
.opp-v2.opp-home .realestate-main .owl-nav .owl-next:focus-visible {
    border-color: var(--opp-ink);
}

/* a narrower lane on a phone, for smaller arrows */
@media (max-width: 575px) {
    .opp-v2.opp-home .realestate-main {
        padding: 0 38px;
    }

    .opp-v2.opp-home .realestate-main .owl-nav .owl-prev,
    .opp-v2.opp-home .realestate-main .owl-nav .owl-next {
        width: 36px;
        height: 36px;
        font-size: 18px;
    }

    .opp-v2.opp-home .realestate-main .owl-nav .owl-prev {
        left: 0;
    }

    .opp-v2.opp-home .realestate-main .owl-nav .owl-next {
        right: 0;
    }
}

/* The section's own spacing is Bootstrap utilities (up to mt-5 pt-5 and pb-5 mb-5), which left
   about 100px above the heading and 120px under View More. These win over them. */
.inves-opportunities-section.opp-home-sec {
    margin-top: 0 !important;
    margin-bottom: 0 !important;
    padding-top: 48px !important;
    padding-bottom: 48px !important;
}

.inves-opportunities-section.opp-home-sec > .container {
    margin-top: 0 !important;
    margin-bottom: 0 !important;
}

/* the building drawing hangs above the heading; with less space above, it would reach into the section before */
.inves-opportunities-section.opp-home-sec .inves-opportunities-icon {
    top: -2rem;
}

@media (max-width: 575px) {
    .inves-opportunities-section.opp-home-sec {
        padding-top: 32px !important;
        padding-bottom: 32px !important;
    }
}
