0 Votes

Changes for page Home

Last modified by Alex Cotiugă on 2026/01/13 13:12

From version 7.27
edited by Alex Cotiugă
on 2025/11/13 11:16
Change comment: There is no comment for this version
To version 7.78
edited by Alex Cotiugă
on 2025/11/13 20:53
Change comment: There is no comment for this version

Summary

Details

Page properties
Content
... ... @@ -3,228 +3,216 @@
3 3  Agnease helps organizations maintain, upgrade, and extend their XWiki environments with clarity and precision. Focusing on stability, performance, and long-term support we ensure your business knowledge and collaboration tools remain dependable, secure, and adaptable to growth.*#
4 4  {{html clean="false"}}
5 5  <main class="agnease-landing">
6 - <!-- ================= HERO ================= -->
7 - <section class="hero hero-centered" aria-labelledby="hero-title">
8 - <div class="container">
9 - <div class="hero-inner">
10 - <h1 id="hero-title">Professional XWiki solutions, from setup to long-term stability</h1>
11 - <p class="lead">Need your XWiki upgraded, secured, or improved? Let’s make it happen</p>
12 - <div class="hero-cta">
13 - <a class="btn btn-primary" href="#contact" aria-label="Schedule a call with Agnease">Request a consultation</a>
6 + <!-- ================= HERO ================= -->
7 + <section class="hero hero-centered" aria-labelledby="hero-title">
8 + <div class="container">
9 + <div class="row">
10 + <div class="col-sm-12">
11 + <div class="hero-inner">
12 + <h1 id="hero-title">Professional XWiki solutions, from setup to long-term stability</h1>
13 + <p class="lead">Need your XWiki upgraded, secured, or improved? Let’s make it happen</p>
14 + <div class="hero-cta">
15 + <a class="btn btn-primary" href="#contact" aria-label="Schedule a call with Agnease">
16 + Request a consultation
17 + </a>
18 + </div>
19 + <ul class="benefits">
20 + <li>Smooth upgrades</li>
21 + <li>Reliable support plans</li>
22 + <li>Custom integrations</li>
23 + <li>Secure, optimized platforms</li>
24 + </ul>
14 14   </div>
15 - <ul class="benefits">
16 - <li>Smooth upgrades</li>
17 - <li>Reliable support plans</li>
18 - <li>Custom integrations</li>
19 - <li>Secure, optimized platforms</li>
20 - </ul>
21 21   </div>
22 22   </div>
23 - </section>
28 + </div>
29 + </section>
24 24  
25 - <!-- ========= WHY CHOOSE AGNEASE (widgets) ========= -->
26 - #set ($whyArray = [{
27 - 'title': 'Stability & security',
28 - 'icon': 'shield',
29 - 'content': 'Proven upgrade steps, rollback safety, and proactive hardening keep your wiki reliable.'
30 - },{
31 - 'title': 'Predictable delivery',
32 - 'icon': 'check-square-o',
33 - 'content': 'Clear scope, defined steps, and documented results to avoid surprises.'
34 - },{
35 - 'title': 'Clean integrations',
36 - 'icon': 'link',
37 - 'content': 'Maintainable SSO, API, and system connections tailored to your environment.'
38 - },{
39 - 'title': 'Long-term support',
40 - 'icon': 'life-ring',
41 - 'content': 'Guaranteed response times, regular checks, and fast assistance when needed.'
42 - }])
43 - <section aria-labelledby="why-title">
44 - <div class="container">
45 - <h2 id="why-title">Why choose Agnease</h2>
46 - <p class="lead">10+ years of XWiki expertise with structured delivery and lasting collaboration</p>
47 - <div class="widgets" role="list">
48 - #foreach ($entry in $whyArray)
49 - <article class="widget" role="listitem">
50 - <div class="icon" aria-hidden="true">
51 - <i class="fa fa-$entry.icon"></i>
52 - <h4>$entry.title</h4>
53 - </div>
54 - <p>$entry.content</p>
55 - </article>
56 - #end
57 - </div>
31 + <!-- ========= WHY CHOOSE AGNEASE (widgets) ========= -->
32 + #set ($whySectionData = [{
33 + 'title': 'Stability & security',
34 + 'icon': 'shield',
35 + 'content': 'Proven upgrade steps, rollback safety, and proactive hardening keep your wiki reliable.'
36 + },{
37 + 'title': 'Predictable delivery',
38 + 'icon': 'check-square-o',
39 + 'content': 'Clear scope, defined steps, and documented results to avoid surprises.'
40 + },{
41 + 'title': 'Clean integrations',
42 + 'icon': 'link',
43 + 'content': 'Maintainable SSO, API, and system connections tailored to your environment.'
44 + },{
45 + 'title': 'Long-term support',
46 + 'icon': 'life-ring',
47 + 'content': 'Guaranteed response times, regular checks, and fast assistance when needed.'
48 + }])
49 + <section aria-labelledby="why-title">
50 + <div class="container">
51 + <h2 id="why-title">Why choose Agnease</h2>
52 + <p class="lead">10+ years of XWiki expertise with structured delivery and lasting collaboration</p>
53 + <div class="row widgets" role="list">
54 + #foreach ($entry in $whySectionData)
55 + <div class="widget col-sm-6 col-md-3" role="listitem">
56 + <div class="icon" aria-hidden="true">
57 + <i class="fa fa-$entry.icon"></i>
58 + <h4>$entry.title</h4>
59 + </div>
60 + <p>$entry.content</p>
61 + </div>
62 + #end
58 58   </div>
59 - </section>
60 - <!-- ================= SERVICES ================= -->
61 - <section class="services" aria-labelledby="services-title">
64 + </div>
65 + </section>
66 + <!-- ================= SERVICES ================= -->
67 + #set ($servicesSectionData = [{
68 + 'title': 'Upgrades',
69 + 'icon': 'refresh',
70 + 'content': 'Stay current with the latest XWiki LTS and keep your instance secure and stable.',
71 + 'items': [
72 + 'Audit setup, extensions, and configurations',
73 + 'Test upgrades with backups and validation',
74 + 'Safe production rollout with minimal downtime'
75 + ]
76 + },{
77 + 'title': 'Maintenance, Support & Recovery',
78 + 'icon': 'stethoscope',
79 + 'content': 'Ensure long-term stability and quick response when issues appear.',
80 + 'items': [
81 + 'Monitoring and performance checks',
82 + 'Security patching, log analysis, triage',
83 + 'Issue recovery, data repair, hardening'
84 + ]
85 + },{
86 + 'title': 'Development & Integrations',
87 + 'icon': 'cogs',
88 + 'content': 'Extend and connect XWiki to fit your workflow and systems.',
89 + 'items': [
90 + 'Custom apps, macros, automation',
91 + 'SSO, REST APIs, LDAP, CRM links',
92 + 'Maintainable extensions for long-term use'
93 + ]
94 + },{
95 + 'title': 'Hosting & Deployment',
96 + 'icon': 'cloud',
97 + 'content': 'Cloud-ready environments designed for reliability and performance.',
98 + 'items': [
99 + 'Containerized deployment and TLS',
100 + 'Backups, restore strategy, observability',
101 + 'Optimization and load tuning'
102 + ]
103 + },{
104 + 'title': 'Migrations to XWiki',
105 + 'icon': 'exchange',
106 + 'content': 'Move from Confluence, SharePoint, or MediaWiki to XWiki with full data integrity and structure.',
107 + 'items': [
108 + 'Preserve hierarchy, attachments, and permissions',
109 + 'Convert macros, categories, and metadata for XWiki',
110 + 'Redirect old URLs and maintain SEO consistency'
111 + ]
112 + }])
113 + <section class="services" aria-labelledby="services-title">
62 62   <div class="container">
63 63   <h2 id="services-title">Services</h2>
64 64   <p class="services-sub">All the XWiki services you need, delivered with precision and care</p>
65 -
66 66   <div class="services-grid">
67 - <!-- Upgrades & Migrations -->
68 - <article class="service">
69 - <i class="fa fa-refresh" aria-hidden="true"></i>
70 - <div class="body">
71 - <h3>Upgrades &amp; Migrations</h3>
72 - <p>Predictable paths to current LTS with low downtime and rollback safety.</p>
73 - <ul>
74 - <li>Version &amp; extension audit, test upgrade</li>
75 - <li>Backups, rollback plan, post-upgrade checks</li>
76 - </ul>
77 - </div>
78 - </article>
79 -
80 - <!-- Maintenance & Support -->
81 - <article class="service">
82 - <i class="fa fa-stethoscope" aria-hidden="true"></i>
83 - <div class="body">
84 - <h3>Maintenance &amp; Support</h3>
85 - <p>Keep your instance healthy with regular checks and timely assistance.</p>
86 - <ul>
87 - <li>Security patches, log review, health reports</li>
88 - <li>Incident triage with defined response times</li>
89 - </ul>
90 - </div>
91 - </article>
92 -
93 - <!-- Custom Development -->
94 - <article class="service">
95 - <i class="fa fa-cogs" aria-hidden="true"></i>
96 - <div class="body">
97 - <h3>Custom Development</h3>
98 - <p>Macros, apps, and workflow automation tailored to your team.</p>
99 - <ul>
100 - <li>Structured data models, permissions, tests</li>
101 - <li>Documentation and clean handover</li>
102 - </ul>
103 - </div>
104 - </article>
105 -
106 - <!-- Integrations -->
107 - <article class="service">
108 - <i class="fa fa-link" aria-hidden="true"></i>
109 - <div class="body">
110 - <h3>Integrations</h3>
111 - <p>Maintainable connections to identity and business systems.</p>
112 - <ul>
113 - <li>SSO (OIDC/SAML/LDAP), REST APIs, webhooks</li>
114 - <li>Mappings and importers that survive upgrades</li>
115 - </ul>
116 - </div>
117 - </article>
118 -
119 - <!-- Hosting & Deployment -->
120 - <article class="service">
121 - <i class="fa fa-cloud" aria-hidden="true"></i>
122 - <div class="body">
123 - <h3>Hosting &amp; Deployment</h3>
124 - <p>Cloud-ready setups with backups, observability, and tuning.</p>
125 - <ul>
126 - <li>Containerized deploy, TLS/headers, metrics/logs</li>
127 - <li>Backup/restore strategy and performance tuning</li>
128 - </ul>
129 - </div>
130 - </article>
131 -
132 - <!-- Audit & Recovery -->
133 - <article class="service">
134 - <i class="fa fa-shield" aria-hidden="true"></i>
135 - <div class="body">
136 - <h3>Audit &amp; Recovery</h3>
137 - <p>Stabilize broken instances and harden configuration.</p>
138 - <ul>
139 - <li>Root-cause analysis, dependency audit, fix plan</li>
140 - <li>Distribution Wizard re-run and hardening</li>
141 - </ul>
142 - </div>
143 - </article>
118 + #foreach ($entry in $servicesSectionData)
119 + <article class="service">
120 + <i class="fa fa-$entry.icon" aria-hidden="true"></i>
121 + <div class="body">
122 + <h4>$entry.title</h4>
123 + <p>$entry.content</p>
124 + <ul>
125 + #foreach ($item in $entry.items)
126 + <li>$item</li>
127 + #end
128 + </ul>
129 + </div>
130 + </article>
131 + #end
144 144   </div>
145 145   </div>
146 146   </section>
147 147  
148 - <!-- ================= METRICS ================= -->
149 - <section aria-labelledby="metrics-title">
150 - <div class="container">
151 - <h2 id="metrics-title">Delivery at a glance</h2>
152 - <div class="metrics" role="list">
153 - <div class="metric" role="listitem">
154 - <div class="num">8–12h</div>
155 - <div class="label">Typical LTS upgrade window</div>
156 - </div>
157 - <div class="metric" role="listitem">
158 - <div class="num">&lt;1h</div>
159 - <div class="label">Average service downtime during upgrades</div>
160 - </div>
161 - <div class="metric" role="listitem">
162 - <div class="num">24–48h</div>
163 - <div class="label">First response SLA (plans)</div>
164 - </div>
165 - <div class="metric" role="listitem">
166 - <div class="num">10+ yrs</div>
167 - <div class="label">XWiki expertise</div>
168 - </div>
136 + <!-- ================= METRICS ================= -->
137 + <section aria-labelledby="metrics-title">
138 + <div class="container">
139 + <h2 id="metrics-title">Delivery at a glance</h2>
140 + <div class="metrics" role="list">
141 + <div class="metric" role="listitem">
142 + <div class="num">8–12h</div>
143 + <div class="label">Typical LTS upgrade window</div>
169 169   </div>
170 - <p class="lead" style="margin-top:.6rem">*for rehearsed, staged upgrades on supported environments.</p>
145 + <div class="metric" role="listitem">
146 + <div class="num">&lt;1h</div>
147 + <div class="label">Average service downtime during upgrades</div>
148 + </div>
149 + <div class="metric" role="listitem">
150 + <div class="num">24–48h</div>
151 + <div class="label">First response SLA (plans)</div>
152 + </div>
153 + <div class="metric" role="listitem">
154 + <div class="num">10+ yrs</div>
155 + <div class="label">XWiki expertise</div>
156 + </div>
171 171   </div>
172 - </section>
158 + <p class="lead" style="margin-top:.6rem">*for rehearsed, staged upgrades on supported environments.</p>
159 + </div>
160 + </section>
173 173  
174 - <!-- ================= PROCESS ================= -->
175 - <section aria-labelledby="process-title">
176 - <div class="container">
177 - <h2 id="process-title">Process</h2>
178 - <p class="lead">Calm, predictable, and transparent from start to finish.</p>
179 - <div class="steps">
180 - <div class="step">
181 - <h3>1) Assess</h3>
182 - <p>Review environment, extensions, constraints, and risks with no surprises.</p>
183 - </div>
184 - <div class="step">
185 - <h3>2) Plan</h3>
186 - <p>Agree scope, milestones, downtime windows, and rollback checkpoints.</p>
187 - </div>
188 - <div class="step">
189 - <h3>3) Deliver</h3>
190 - <p>Execute, verify, document, and hand over with actionable notes.</p>
191 - </div>
162 + <!-- ================= PROCESS ================= -->
163 + <section aria-labelledby="process-title">
164 + <div class="container">
165 + <h2 id="process-title">Process</h2>
166 + <p class="lead">Calm, predictable, and transparent from start to finish.</p>
167 + <div class="steps">
168 + <div class="step">
169 + <h3>1) Assess</h3>
170 + <p>Review environment, extensions, constraints, and risks with no surprises.</p>
192 192   </div>
172 + <div class="step">
173 + <h3>2) Plan</h3>
174 + <p>Agree scope, milestones, downtime windows, and rollback checkpoints.</p>
175 + </div>
176 + <div class="step">
177 + <h3>3) Deliver</h3>
178 + <p>Execute, verify, document, and hand over with actionable notes.</p>
179 + </div>
193 193   </div>
194 - </section>
181 + </div>
182 + </section>
195 195  
196 - <!-- ================= FAQ ================= -->
197 - <section class="faq" aria-labelledby="faq-title">
198 - <div class="container">
199 - <h2 id="faq-title">FAQ</h2>
200 - <details>
201 - <summary>How much downtime should we expect for an upgrade?</summary>
202 - <p>Most upgrades complete in a short maintenance window. For mission-critical wikis we rehearse and stage changes to minimize downtime.</p>
203 - </details>
204 - <details>
205 - <summary>Can you help if our wiki is already broken?</summary>
206 - <p>Yes. We start with an audit to stabilize the instance, recover missing features, and harden configuration.</p>
207 - </details>
208 - <details>
209 - <summary>Do you offer support plans?</summary>
210 - <p>Yes, from ad-hoc assistance to ongoing retainers with response-time guarantees and monthly health checks.</p>
211 - </details>
212 - </div>
213 - </section>
184 + <!-- ================= FAQ ================= -->
185 + <section class="faq" aria-labelledby="faq-title">
186 + <div class="container">
187 + <h2 id="faq-title">FAQ</h2>
188 + <details>
189 + <summary>How much downtime should we expect for an upgrade?</summary>
190 + <p>Most upgrades complete in a short maintenance window. For mission-critical wikis we rehearse and stage changes to minimize downtime.</p>
191 + </details>
192 + <details>
193 + <summary>Can you help if our wiki is already broken?</summary>
194 + <p>Yes. We start with an audit to stabilize the instance, recover missing features, and harden configuration.</p>
195 + </details>
196 + <details>
197 + <summary>Do you offer support plans?</summary>
198 + <p>Yes, from ad-hoc assistance to ongoing retainers with response-time guarantees and monthly health checks.</p>
199 + </details>
200 + </div>
201 + </section>
214 214  
215 - <!-- ================= CTA ================= -->
216 - <section id="contact" aria-labelledby="contact-title">
217 - <div class="container">
218 - <div class="cta-band">
219 - <div>
220 - <h3 id="contact-title">Need a reliable plan for your XWiki?</h3>
221 - <p class="lead" style="margin:0">Upgrades, support, and integrations handled with low risk and clear communication.</p>
222 - </div>
223 - <a class="btn btn-primary" href="mailto:hello@agnease.com">Contact Agnease</a>
203 + <!-- ================= CTA ================= -->
204 + <section id="contact" aria-labelledby="contact-title">
205 + <div class="container">
206 + <div class="cta-band">
207 + <div>
208 + <h3 id="contact-title">Need a reliable plan for your XWiki?</h3>
209 + <p class="lead" style="margin:0">Upgrades, support, and integrations handled with low risk and clear communication.</p>
224 224   </div>
211 + <a class="btn btn-primary" href="mailto:hello@agnease.com">Contact Agnease</a>
225 225   </div>
226 - </section>
227 - </main>
213 + </div>
214 + </section>
215 +</main>
228 228  {{/html}}
229 229  #*
230 230  = XWiki Multi-Factor Authentication (MFA) Application =
XWiki.StyleSheetExtension[0]
Code
... ... @@ -22,7 +22,7 @@
22 22   h2 { font-size: clamp(1.4rem, 1.4vw + .8rem, 2rem); line-height: 1.2; margin: .2rem 0 .4rem; }
23 23   h3 { font-size: 1.12rem; margin: .2rem 0 .25rem; }*/
24 24   .lead { color: @muted; max-width: 72ch; }
25 - .container { max-width: @maxw; margin-top: 5px; padding: 0;}
25 + .container { max-width: @maxw; margin-top: 5px; padding: 0; overflow-x: clip;}
26 26  
27 27   /* Global sections */
28 28   section { padding: 32px 0; border-top: 1px solid @line; }
... ... @@ -120,138 +120,192 @@
120 120   }
121 121   }
122 122  
123 - /* === WHY CHOOSE (widgets with inline icon + title) === */
123 + /* === WHY CHOOSE (widgets using Bootstrap grid) === */
124 124   .widgets {
125 - display: grid;
126 - gap: 16px;
127 - grid-template-columns: 1fr;
125 + margin-top: 12px;
128 128  
129 - @media (min-width: 860px) {
130 - grid-template-columns: repeat(4, 1fr);
131 - }
132 - }
133 -
134 - .widget {
135 - background: #fff;
136 - border: 1px solid @line;
137 - border-radius: @radius;
138 - padding: 18px;
139 - box-shadow: @shadow-sm;
127 + /* Flexbox makes Bootstrap columns equal height */
140 140   display: flex;
141 - flex-direction: column;
142 - justify-content: flex-start;
143 - gap: 8px;
144 - text-align: left;
145 - transition: transform 0.18s ease, box-shadow 0.18s ease;
129 + flex-wrap: wrap;
146 146  
147 - &:hover {
148 - transform: translateY(-2px);
149 - box-shadow: @shadow;
150 - }
131 + /* Remove default Bootstrap left/right gutters
132 + so cards align with the section heading */
133 + margin-left: -15px;
134 + margin-right: -15px;
151 151  
152 - /* The icon + title row */
153 - .icon {
136 + /* Cards (inside columns) */
137 + .widget {
138 + /* Bootstrap grid classes remain active (col-sm-6 col-md-3) */
154 154   display: flex;
155 - align-items: center;
156 - gap: 10px;
157 - padding: 6px 0;
158 - border-bottom: 1px solid fade(@line, 60%);
159 - margin-bottom: 6px;
140 + flex-direction: column;
141 + height: 100%;
160 160  
161 - i {
162 - color: @brand;
143 + /* Card styling */
144 + padding: 18px;
145 + background: #fff;
146 + border: 1px solid @line;
147 + border-radius: @radius;
148 + box-shadow: @shadow-sm;
149 + transition: transform .18s ease, box-shadow .18s ease;
150 +
151 + &:hover {
152 + transform: translateY(-2px);
153 + box-shadow: @shadow;
163 163   }
164 164  
165 - h4 {
166 - /*font-weight: 700; */
156 + /* Icon row */
157 + .icon {
158 + display: flex;
159 + align-items: center;
160 + gap: 10px;
161 + padding-bottom: 6px;
162 + margin-bottom: 8px;
163 + border-bottom: 1px solid fade(@line, 60%);
164 +
165 + i {
166 + color: @brand;
167 + }
168 +
169 + h4 {
170 + margin: 0;
171 + line-height: 1.2;
172 + color: @text;
173 + }
174 + }
175 +
176 + /* Card text */
177 + p {
167 167   margin: 0;
168 - color: @text;
169 - line-height: 1.2;
179 + line-height: 1.45;
180 + color: @muted;
170 170   }
171 171   }
172 172  
173 - /* Body paragraph */
174 - p {
175 - color: @muted;
176 - margin: 0;
177 - line-height: 1.45;
184 + /* Mobile spacing */
185 + @media (max-width: 767px) {
186 + .widget {
187 + margin-bottom: 16px;
188 + }
178 178   }
179 179   }
180 180  
181 - /* SERVICES */
182 - .services-sub {
183 - margin: 0 0 1.25rem;
184 - color: #5b6a72;
185 - }
186 186  
187 - /* Feature list layout */
188 - .feature-list {
189 - display: grid;
190 - grid-template-columns: repeat(auto-fit, minmax(480px, 1fr));
191 - gap: 24px 32px;
192 - list-style: none;
193 - margin: 0;
194 - padding: 0;
195 - border-top: 1px solid rgba(0,0,0,0.08);
196 - }
193 + /* SERVICES */
194 + .services {
195 + h2 {
196 + margin: 0 0 .3rem;
197 + }
197 197  
198 - /* Each item is a two-column media object: icon + content */
199 - .feature-list li {
200 - display: grid;
201 - grid-template-columns: 28px 1fr;
202 - gap: 14px;
203 - padding: 18px 0;
204 - border-top: 1px solid rgba(0,0,0,0.08);
205 - }
206 - .feature-list li:first-child { border-top: none; }
199 + .services-sub {
200 + margin: 0 0 1.75rem;
201 + color: @muted;
202 + }
207 207  
208 - /* Icon */
209 - .feature-list i {
210 - color: #008e78; /* brand accent */
211 - font-size: 20px;
212 - line-height: 1;
213 - margin-top: 3px; /* optical align with title */
214 - }
204 + /* Flex layout: 2 per row on desktop */
205 + .services-grid {
206 + display: flex;
207 + flex-wrap: wrap;
208 + gap: 32px 36px; // row gap, column gap
209 + }
215 215  
216 - /* Content block */
217 - .feature-list .content h3 {
218 - margin: 0 0 4px;
219 - font-size: 1.125rem; /* 18px */
220 - font-weight: 700;
221 - }
222 - .feature-list .content p {
223 - margin: 0 0 6px;
224 - color: #2c3940;
225 - line-height: 1.5;
226 - }
211 + .service {
212 + display: grid;
213 + grid-template-columns: 48px 1fr;
214 + gap: 16px;
215 + padding: 18px 0;
216 + border-top: 1px solid @line;
227 227  
228 - /* Details link (consistent button-ish link) */
229 - .feature-list .details {
230 - display: inline-block;
231 - font-weight: 700;
232 - color: #0a3c37;
233 - text-decoration: none;
234 - border: 1.5px solid #008e78;
235 - background: #e8fbf7;
236 - border-radius: 10px;
237 - padding: 6px 10px;
238 - }
239 - .feature-list .details:hover {
240 - background: #d7f6ef;
241 - }
218 + /* two per row */
219 + flex: 1 1 calc(50% - 18px);
220 + max-width: calc(50% - 18px);
242 242  
243 - /* Responsive: slightly looser spacing on small screens */
244 - @media (max-width: 640px) {
245 - .feature-list li {
246 - gap: 12px;
247 - padding: 14px 0;
222 + /* first row: no top border */
223 + &:nth-of-type(-n + 2) {
224 + border-top: none;
225 + }
226 +
227 + > i {
228 + width: 42px;
229 + height: 42px;
230 + border-radius: 50%;
231 + display: flex;
232 + align-items: center;
233 + justify-content: center;
234 + font-size: 18px;
235 + color: @brand;
236 + background: fade(@brand, 10%);
237 + margin-top: 3px;
238 + }
239 +
240 + .body {
241 + h4 {
242 + margin: 0 0 4px;
243 + font-size: 1.125rem;
244 + font-weight: 800;
245 + }
246 +
247 + p {
248 + margin: 0 0 6px;
249 + color: @text;
250 + line-height: 1.5;
251 + }
252 +
253 + ul {
254 + margin: .45rem 0 0;
255 + padding-left: 1.1rem;
256 + color: @muted;
257 + font-size: .95rem;
258 + }
259 +
260 + li {
261 + margin: .25rem 0;
262 + line-height: 1.45;
263 + }
264 + }
248 248   }
249 - .feature-list i {
250 - font-size: 18px;
251 - margin-top: 4px;
266 +
267 + /* If there is an odd number of services, center the last one */
268 + .services-grid > .service:last-child:nth-child(odd) {
269 + flex-basis: 100%;
270 + max-width: 680px;
271 + margin-left: auto;
272 + margin-right: auto;
252 252   }
253 - }
254 254  
275 + /* Mobile: single column, full-width */
276 + @media (max-width: 760px) {
277 + .services-grid {
278 + gap: 20px;
279 + }
280 +
281 + .service {
282 + grid-template-columns: 40px 1fr;
283 + flex: 1 1 100%;
284 + max-width: 100%;
285 +
286 + /* reset border for all, then remove only on first */
287 + border-top: 1px solid @line;
288 +
289 + &:nth-of-type(1) {
290 + border-top: none;
291 + }
292 +
293 + > i {
294 + width: 36px;
295 + height: 36px;
296 + font-size: 16px;
297 + }
298 + }
299 +
300 + /* On mobile, last item behaves like all others */
301 + .services-grid > .service:last-child:nth-child(odd) {
302 + flex-basis: 100%;
303 + max-width: 100%;
304 + margin-left: 0;
305 + margin-right: 0;
306 + }
307 + }
308 + }
255 255   /* METRICS */
256 256   .metrics {
257 257   display: grid; gap: 14px; grid-template-columns: repeat(2, 1fr);
... ... @@ -302,12 +302,6 @@
302 302   background-attachment: scroll;
303 303   }
304 304  
305 - /* Fix possible grid or card overshoot */
306 - .container {
307 - max-width: 100%;
308 - overflow-x: clip; /* hides subtle pixel overflow without scroll */
309 - }
310 -
311 311   /* Safety for large paddings/margins that might extend */
312 312   section, .widgets, .services, .metrics, .steps {
313 313   margin-left: auto;