Onde as cargas encontram o destino

O Porto de Lisboa situa-se na proximidade do maior centro de consumo do país, a sua localização privilegiada e as excelentes condições naturais tornam-no numa infraestrutura vital para a economia de Portugal. 

Os seus 16 terminais permitem receber diferentes tipos de carga: contentores, granéis líquidos e sólidos, Ro-Ro e fracionada. O Porto de Lisboa oferece ainda uma completa rede de ligações com os principais portos do mundo, através de 24 linhas de navegação regulares, onde estão representados os principais armadores internacionais.

Ocorreu um erro ao processar o template.
The following has evaluated to null or missing:
==> title  [in template "20097#20125#66237" at line 125, column 51]

----
Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----

----
FTL stack trace ("~" means nesting-related):
	- Failed at: ${title.getData()}  [in template "20097#20125#66237" at line 125, column 49]
----
1<#-- SliderNumbers.ftl --> 
2<#-- _<@portlet.namespace /> --> 
3<style> 
4 
5/* Seção de apresentação com margem superior */ 
6.maringTopPresentation { 
7  margin-top: 7%; 
8  min-height: 770px; 
9
10 
11/* Paginação do slider */ 
12.sliderPagination${randomNamespace} { 
13  display: none; 
14
15 
16.sliderPagination${randomNamespace} .is-active { 
17  transform: unset; 
18  background: #82c6e2; 
19  opacity: 1; 
20
21 
22/* Indicadores do slider */ 
23.sliderIndicators${randomNamespace} { 
24  background: #82c6e2; 
25  opacity: 0.2; 
26  width: 6px; 
27  height: 6px; 
28
29 
30/* Botões de navegação do slider */ 
31.sliderPrev_${randomNamespace}, 
32.sliderNext_${randomNamespace} { 
33  width: 44px; 
34  height: 44px; 
35  background-color: #fff; 
36  opacity: 0.5; 
37  border-radius: 5px; 
38
39 
40.sliderPrev_${randomNamespace} { 
41  left: 0; 
42
43 
44.sliderNext_${randomNamespace} { 
45  right: 0; 
46
47 
48/* Media Query para telas menores que 767px */ 
49@media only screen and (max-width: 767px) { 
50  .sliderPagination${randomNamespace} { 
51    display: flex; 
52    bottom: 2.5em; 
53
54 
55  .numbDiv { 
56    padding: 65px 0; 
57
58 
59  .sliderPrev_${randomNamespace}, 
60  .sliderNext_${randomNamespace} { 
61    top: 60%; 
62
63 
64  .sliderNext_${randomNamespace} { 
65    right: 48%; 
66    transform: translateX(100%); 
67
68 
69  .sliderPrev_${randomNamespace} { 
70    left: 48%; 
71    transform: translateX(-100%); 
72
73  .gfi .slider-DeepSea .silhuetas_lisboa { 
74       margin-top: 0; 
75
76  .gfi .slider-DeepSea .silhuetas_lisboa .wave-contents.buildings { 
77    min-height: 300px; 
78
79  .gfi .slider-DeepSea .silhuetas_lisboa .back div { 
80    height: 250px !important; 
81
82
83 
84/* Estilos gerais para a classe .back */ 
85.back div { 
86  height: 350px !important; 
87  align-content: end !important; 
88
89 
90.back img { 
91  max-height: 350px; 
92  width: auto; 
93
94 
95/* Imagens flutuadas para diferentes variantes */ 
96.back_1 img { 
97  float: right; 
98
99 
100.back_3 img { 
101  float: left; 
102
103 
104/* Container centralizado com z-index */ 
105.back_2, 
106.back_3 { 
107  width: 100%; 
108  position: absolute; 
109  z-index: 5; 
110  top: 0; 
111  height: 306px; 
112  text-align: center; 
113
114 
115.back_3 { 
116  align-content: end; 
117
118 
119</style> 
120<#assign counterEntries = 0> 
121<div class="slider-DeepSea sliderContainer  deepSea_Bk"  style="margin-top:-10px"> 
122	<div class="wave" style="background-color: #E5EEF1"></div> 
123	 
124	<div  class="container deepSea_Bk block-numbers"  data-aos="fade-up" data-aos-duration="1000"> 
125	    <h2 class=" descriptiveBannerTitle">${title.getData()}</h2> 
126		<div id="splide_${randomNamespace}" class="splide"> 
127			<div class="splide__arrows"> 
128				<button class="splide__arrow splide__arrow--prev sliderPrev_${randomNamespace}"> 
129					<svg style="width:30px; height:30px; fill: #14213d"> 
130						<use href="/o/apl-theme/images/icons.svg#IconKeyboardArrowRightRounded"></use> 
131					</svg> 
132				</button> 
133				<button class="splide__arrow splide__arrow--next sliderNext_${randomNamespace}"> 
134					<svg style="width: 30px; height: 30px; fill: #14213d"> 
135						<use href="/o/apl-theme/images/icons.svg#IconKeyboardArrowRightRounded"></use> 
136					</svg> 
137				</button> 
138			</div> 
139			<div class="splide__track"> 
140				<div class="splide__list"> 
141					<#if numb?? && numb.getSiblings()?has_content> 
142						<#list numb.getSiblings() as cur_numb> 
143							<#assign counterEntries=counterEntries + 1> 
144								<div class="splide__slide"> 
145									<div class="numbDiv"> 
146										<p class="numbInfo">${cur_numb.getData()}</p> 
147										<p class="numbDesc">${cur_numb.desc.getData()}</p> 
148									</div> 
149								</div> 
150						</#list> 
151					</#if> 
152				</div> 
153			</div> 
154		</div> 
155	</div> 
156	<div class="silhuetas_lisboa"> 
157		<div class="wave-contents buildings"> 
158			<div class="back"> 
159			 
160			   <div class="back_3"> 
161			     <div data-aos="fade-left" data-aos-duration="1000" class="aos-init aos-animate"> 
162			       <img src="/o/apl-theme/images/background/silhuetas_lisboa_back3.svg" alt="" style="float: left;     margin-bottom: 0 !important;" > 
163			     </div>  
164			     </div> 
165			  
166			 <div class="back_2"> 
167			     <div data-aos="fade-right" data-aos-duration="1500" class="aos-init aos-animate"> 
168			        <img src="/o/apl-theme/images/background/silhuetas_lisboa_back2.svg" alt="" > 
169			     </div> 
170			 </div> 
171			  
172            <div class="back_1" data-aos="fade-left" data-aos-duration="2000" class="aos-init aos-animate"> 
173                <img src="/o/apl-theme/images/background/silhuetas_lisboa_back1.svg" alt=""  > 
174            </div> 
175             
176            <div class="mid"> 
177				<div data-aos="fade-right" data-aos-duration="1000" class="aos-init aos-animate"> 
178					<img src="/o/apl-theme/images/background/silhuetas_lisboa_mid.svg" alt=""> 
179				</div> 
180			</div> 
181			<div class="front"> 
182				<div data-aos="fade-right" data-aos-duration="3000" class="aos-init aos-animate"> 
183					<img src="/o/apl-theme/images/background/silhuetas_lisboa_front.svg" alt=""> 
184				</div> 
185			</div> 
186			</div> 
187		</div>			 
188	</div> 
189</div> 
190 
191<script> 
192<#-- IMPORTANTE: DEFINIR AQUI O NUMERO DE ITENS POR PAGINA PARA MOBILE / TABLET / DESKTOP --> 
193<#-- Desktop --> 
194<#assign slidesPerPageDesktop = 3> 
195<#-- Tablet --> 
196<#assign slidesPerPageTablet = 3> 
197<#-- Mobile --> 
198<#assign slidesPerPageMobile = 1> 
199 
200<#-- Define drag default --> 
201var isDraggableDesktop = true; 
202var isDraggableTablet = true; 
203var isDraggableMobile = true; 
204 
205<#-- Desativa o drag se o numero de entradas for menor que o numero de itens por página--> 
206if (${counterEntries} < (${slidesPerPageDesktop} + 1)){ 
207    isDraggableDesktop = false; 
208
209if (${counterEntries} < (${slidesPerPageTablet} + 1)){ 
210    isDraggableTablet = false; 
211
212if (${counterEntries} < (${slidesPerPageMobile} + 1)){ 
213    isDraggableMobile = false; 
214
215 
216<#-- Configuração do slider que irá ser criado --> 
217    var splide_${randomNamespace} = new Splide( '#splide_${randomNamespace}', { 
218    perPage: 3, 
219   <#-- perPage: ${slidesPerPageDesktop},  -->   
220    perMove: 1, 
221    type: 'loop', 
222    height: 100, 
223    pagination: true, 
224    drag: isDraggableDesktop, 
225    classes: { 
226		// Add classes for pagination. 
227		pagination: 'splide__pagination sliderPagination${randomNamespace}', // container 
228		page      : 'splide__pagination__page sliderIndicators${randomNamespace}', // each button 
229	}, 
230    breakpoints: { 
231		767: { 
232			perPage: ${slidesPerPageMobile}, 
233			height: 300, 
234			drag: isDraggableMobile, 
235
236
237}); 
238 
239<#-- Fazer aparecer ou desaparecer as setas dependendo do numero de páginas (se houver só uma página não queremos setas) --> 
240splide_${randomNamespace}.on( 'mounted resize', function() { 
241    var slid_${randomNamespace} = document.getElementById('splide_${randomNamespace}'); 
242    var uls_${randomNamespace} = slid_${randomNamespace}.getElementsByClassName('splide__pagination'); // todos os ul's 
243    var ul_${randomNamespace} = uls_${randomNamespace}[uls_${randomNamespace}.length - 1]; // ul's com os lis da paginação 
244    var lisCount_${randomNamespace} = ul_${randomNamespace}.childElementCount; // 2 
245    <#-- var lis_${randomNamespace} = ul_${randomNamespace}.children; --> 
246    if (lisCount_${randomNamespace} > 1){ 
247        $(".sliderPrev_${randomNamespace}").css("display", "flex"); 
248        $(".sliderNext_${randomNamespace}").css("display", "flex"); 
249    } else { 
250        document.querySelector("#splide_${randomNamespace} > ul > li:nth-child(1) > button").click(); 
251        $(".sliderPrev_${randomNamespace}").css("display", "none"); 
252        $(".sliderNext_${randomNamespace}").css("display", "none"); 
253
254} ); 
255 
256<#-- Codigo que lança a criação do slider --> 
257splide_${randomNamespace}.mount(); 
258 
259 
260 
261<#-- anime elemento numeros --> 
262document.addEventListener('DOMContentLoaded', () => { 
263  const blockNumbers = document.querySelector('.block-numbers'); 
264 
265  const observer = new IntersectionObserver(entries => { 
266    entries.forEach(entry => { 
267      if (entry.isIntersecting) { 
268        blockNumbers.classList.add('show'); 
269        // Opcional: Para evitar que a animação aconteça várias vezes 
270        observer.unobserve(entry.target); 
271
272    }); 
273  }, { threshold: 0.5 }); // Ativa quando 50% do elemento estiver visível 
274 
275  observer.observe(blockNumbers); 
276}); 
277 
278  
279</script> 
280<script> 
281    AOS.init(); 
282</script> 

Terminais de Carga